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

📄 qca-ossl.cpp

📁 QCA的OPENSSL模块
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                                        ASN1_OBJECT *obj = OBJ_txt2obj("1.3.6.1.5.5.7.8.5", 1); // 1 = only accept dotted input                                        if(OBJ_cmp(other->type_id, obj) != 0)                                                break;                                        ASN1_OBJECT_free(obj);                                        ASN1_TYPE *at = other->value;                                        if(at->type != V_ASN1_UTF8STRING)                                                break;                                        ASN1_UTF8STRING *str = at->value.utf8string;                                        QByteArray buf((const char *)ASN1_STRING_data(str), ASN1_STRING_length(str));                                        info->insert(t, QString::fromUtf8(buf));                                        ++pos;                                }                        }                        break;                }		default:                        break;        }}static CertificateInfo get_cert_alt_name(X509_EXTENSION *ex){	CertificateInfo info;	GENERAL_NAMES *gn = (GENERAL_NAMES *)X509V3_EXT_d2i(ex);	try_get_general_name(gn, Email, &info);	try_get_general_name(gn, URI, &info);	try_get_general_name(gn, DNS, &info);	try_get_general_name(gn, IPAddress, &info);	try_get_general_name(gn, XMPP, &info);	GENERAL_NAMES_free(gn);	return info;}static X509_EXTENSION *new_cert_key_usage(const Constraints &constraints){	ASN1_BIT_STRING *keyusage = 0;	for(int n = 0; n < constraints.count(); ++n)	{		int bit = -1;		switch(constraints[n].known())		{			case DigitalSignature:				bit = Bit_DigitalSignature;				break;			case NonRepudiation:				bit = Bit_NonRepudiation;				break;			case KeyEncipherment:				bit = Bit_KeyEncipherment;				break;			case DataEncipherment:				bit = Bit_DataEncipherment;				break;			case KeyAgreement:				bit = Bit_KeyAgreement;				break;			case KeyCertificateSign:				bit = Bit_KeyCertificateSign;				break;			case CRLSign:				bit = Bit_CRLSign;				break;			case EncipherOnly:				bit = Bit_EncipherOnly;				break;			case DecipherOnly:				bit = Bit_DecipherOnly;				break;			default:				break;		}		if(bit != -1)		{			if(!keyusage)				keyusage = ASN1_BIT_STRING_new();			ASN1_BIT_STRING_set_bit(keyusage, bit, 1);		}	}	if(!keyusage)		return 0;	X509_EXTENSION *ex = X509V3_EXT_i2d(NID_key_usage, 1, keyusage); // 1 = critical	ASN1_BIT_STRING_free(keyusage);	return ex;}static Constraints get_cert_key_usage(X509_EXTENSION *ex){	Constraints constraints;	int bit_table[9] =	{		DigitalSignature,		NonRepudiation,		KeyEncipherment,		DataEncipherment,		KeyAgreement,		KeyCertificateSign,		CRLSign,		EncipherOnly,		DecipherOnly	};	ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING *)X509V3_EXT_d2i(ex);	for(int n = 0; n < 9; ++n)	{		if(ASN1_BIT_STRING_get_bit(keyusage, n))			constraints += ConstraintType((ConstraintTypeKnown)bit_table[n]);	}	ASN1_BIT_STRING_free(keyusage);	return constraints;}static X509_EXTENSION *new_cert_ext_key_usage(const Constraints &constraints){	EXTENDED_KEY_USAGE *extkeyusage = 0;	for(int n = 0; n < constraints.count(); ++n)	{		int nid = -1;		// TODO: don't use known/nid, and instead just use OIDs		switch(constraints[n].known())		{			case ServerAuth:				nid = NID_server_auth;				break;			case ClientAuth:				nid = NID_client_auth;				break;			case CodeSigning:				nid = NID_code_sign;				break;			case EmailProtection:				nid = NID_email_protect;				break;			case IPSecEndSystem:				nid = NID_ipsecEndSystem;				break;			case IPSecTunnel:				nid = NID_ipsecTunnel;				break;			case IPSecUser:				nid = NID_ipsecUser;				break;			case TimeStamping:				nid = NID_time_stamp;				break;			case OCSPSigning:				nid = NID_OCSP_sign;				break;			default:				break;		}		if(nid != -1)		{			if(!extkeyusage)				extkeyusage = sk_ASN1_OBJECT_new_null();			ASN1_OBJECT *obj = OBJ_nid2obj(nid);			sk_ASN1_OBJECT_push(extkeyusage, obj);		}	}	if(!extkeyusage)		return 0;	X509_EXTENSION *ex = X509V3_EXT_i2d(NID_ext_key_usage, 0, extkeyusage); // 0 = not critical	sk_ASN1_OBJECT_pop_free(extkeyusage, ASN1_OBJECT_free);	return ex;}static Constraints get_cert_ext_key_usage(X509_EXTENSION *ex){	Constraints constraints;	EXTENDED_KEY_USAGE *extkeyusage = (EXTENDED_KEY_USAGE *)X509V3_EXT_d2i(ex);	for(int n = 0; n < sk_ASN1_OBJECT_num(extkeyusage); ++n)	{		ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(extkeyusage, n);		int nid = OBJ_obj2nid(obj);		if(nid == NID_undef)			continue;		// TODO: don't use known/nid, and instead just use OIDs		int t = -1;		switch(nid)		{			case NID_server_auth:				t = ServerAuth;				break;			case NID_client_auth:				t = ClientAuth;				break;			case NID_code_sign:				t = CodeSigning;				break;			case NID_email_protect:				t = EmailProtection;				break;			case NID_ipsecEndSystem:				t = IPSecEndSystem;				break;			case NID_ipsecTunnel:				t = IPSecTunnel;				break;			case NID_ipsecUser:				t = IPSecUser;				break;			case NID_time_stamp:				t = TimeStamping;				break;			case NID_OCSP_sign:				t = OCSPSigning;				break;		};		if(t == -1)			continue;		constraints.append(ConstraintType((ConstraintTypeKnown)t));	}	sk_ASN1_OBJECT_pop_free(extkeyusage, ASN1_OBJECT_free);	return constraints;}static X509_EXTENSION *new_cert_policies(const QStringList &policies){	STACK_OF(POLICYINFO) *pols = 0;	for(int n = 0; n < policies.count(); ++n)	{		QByteArray cs = policies[n].toLatin1();		ASN1_OBJECT *obj = OBJ_txt2obj(cs.data(), 1); // 1 = only accept dotted input		if(!obj)			continue;		if(!pols)			pols = sk_POLICYINFO_new_null();		POLICYINFO *pol = POLICYINFO_new();		pol->policyid = obj;		sk_POLICYINFO_push(pols, pol);	}	if(!pols)		return 0;	X509_EXTENSION *ex = X509V3_EXT_i2d(NID_certificate_policies, 0, pols); // 0 = not critical	sk_POLICYINFO_pop_free(pols, POLICYINFO_free);	return ex;}static QStringList get_cert_policies(X509_EXTENSION *ex){	QStringList out;	STACK_OF(POLICYINFO) *pols = (STACK_OF(POLICYINFO) *)X509V3_EXT_d2i(ex);	for(int n = 0; n < sk_POLICYINFO_num(pols); ++n)	{		POLICYINFO *pol = sk_POLICYINFO_value(pols, n);		QByteArray buf(128, 0);		OBJ_obj2txt((char *)buf.data(), buf.size(), pol->policyid, 1); // 1 = only accept dotted input		out += QString::fromLatin1(buf);	}	sk_POLICYINFO_pop_free(pols, POLICYINFO_free);	return out;}static QByteArray get_cert_subject_key_id(X509_EXTENSION *ex){	ASN1_OCTET_STRING *skid = (ASN1_OCTET_STRING *)X509V3_EXT_d2i(ex);	QByteArray out((const char *)ASN1_STRING_data(skid), ASN1_STRING_length(skid));	ASN1_OCTET_STRING_free(skid);	return out;}// If you get any more crashes in this code, please provide a copy// of the cert to bradh AT frogmouth.netstatic QByteArray get_cert_issuer_key_id(X509_EXTENSION *ex){	AUTHORITY_KEYID *akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ex);	QByteArray out;	if (akid->keyid)		out = QByteArray((const char *)ASN1_STRING_data(akid->keyid), ASN1_STRING_length(akid->keyid));	AUTHORITY_KEYID_free(akid);	return out;}static Validity convert_verify_error(int err){	// TODO: ErrorExpiredCA	Validity rc;	switch(err)	{		case X509_V_ERR_CERT_REJECTED:			rc = ErrorRejected;			break;		case X509_V_ERR_CERT_UNTRUSTED:			rc = ErrorUntrusted;			break;		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:		case X509_V_ERR_CERT_SIGNATURE_FAILURE:		case X509_V_ERR_CRL_SIGNATURE_FAILURE:		case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:		case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:			rc = ErrorSignatureFailed;			break;		case X509_V_ERR_INVALID_CA:		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:		case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:			rc = ErrorInvalidCA;			break;		case X509_V_ERR_INVALID_PURPOSE:  // note: not used by store verify			rc = ErrorInvalidPurpose;			break;		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:		case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:			rc = ErrorSelfSigned;			break;		case X509_V_ERR_CERT_REVOKED:			rc = ErrorRevoked;			break;		case X509_V_ERR_PATH_LENGTH_EXCEEDED:			rc = ErrorPathLengthExceeded;			break;		case X509_V_ERR_CERT_NOT_YET_VALID:		case X509_V_ERR_CERT_HAS_EXPIRED:		case X509_V_ERR_CRL_NOT_YET_VALID:		case X509_V_ERR_CRL_HAS_EXPIRED:		case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:		case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:		case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:		case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:			rc = ErrorExpired;			break;		case X509_V_ERR_APPLICATION_VERIFICATION:		case X509_V_ERR_OUT_OF_MEM:		case X509_V_ERR_UNABLE_TO_GET_CRL:		case X509_V_ERR_CERT_CHAIN_TOO_LONG:		default:			rc = ErrorValidityUnknown;			break;	}	return rc;}EVP_PKEY *qca_d2i_PKCS8PrivateKey(const SecureArray &in, EVP_PKEY **x, pem_password_cb *cb, void *u){	PKCS8_PRIV_KEY_INFO *p8inf;	// first try unencrypted form	BIO *bi = BIO_new(BIO_s_mem());	BIO_write(bi, in.data(), in.size());	p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(bi, NULL);	BIO_free(bi);	if(!p8inf)	{		X509_SIG *p8;		// now try encrypted form		bi = BIO_new(BIO_s_mem());		BIO_write(bi, in.data(), in.size());		p8 = d2i_PKCS8_bio(bi, NULL);		BIO_free(bi);		if(!p8)			return NULL;		// get passphrase		char psbuf[PEM_BUFSIZE];		int klen;		if(cb)			klen = cb(psbuf, PEM_BUFSIZE, 0, u);		else			klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);		if(klen <= 0)		{			PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ);			X509_SIG_free(p8);			return NULL;		}		// decrypt it		p8inf = PKCS8_decrypt(p8, psbuf, klen);		X509_SIG_free(p8);		if(!p8inf)			return NULL;	}	EVP_PKEY *ret = EVP_PKCS82PKEY(p8inf);	PKCS8_PRIV_KEY_INFO_free(p8inf);	if(!ret)		return NULL;	if(x)	{		if(*x)			EVP_PKEY_free(*x);		*x = ret;	}	return ret;}class opensslHashContext : public HashContext{public:    opensslHashContext(const EVP_MD *algorithm, Provider *p, const QString &type) : HashContext(p, type)    {	m_algorithm = algorithm;	EVP_DigestInit( &m_context, m_algorithm );    }    ~opensslHashContext()    {	EVP_MD_CTX_cleanup(&m_context);    }    void clear()    {	EVP_MD_CTX_cleanup(&m_context);	EVP_DigestInit( &m_context, m_algorithm );    }    void update(const MemoryRegion &a)    {	EVP_DigestUpdate( &m_context, (unsigned char*)a.data(), a.size() );    }    MemoryRegion final()    {	SecureArray a( EVP_MD_size( m_algorithm ) );	EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 );	return a;    }    Provider::Context *clone() const    {	return new opensslHashContext(*this);    }protected:    const EVP_MD *m_algorithm;    EVP_MD_CTX m_context;};class opensslPbkdf1Context : public KDFContext{public:    opensslPbkdf1Context(const EVP_MD *algorithm, Provider *p, const QString &type) : KDFContext(p, type)    {	m_algorithm = algorithm;	EVP_DigestInit( &m_context, m_algorithm );    }    Provider::Context *clone() const    {	return new opensslPbkdf1Context( *this );    }    SymmetricKey makeKey(const SecureArray &secret, const InitializationVector &salt,			      unsigned int keyLength, unsigned int iterationCount)    {	/* from RFC2898:	   Steps:	   1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output	   "derived key too long" and stop.	*/	if ( keyLength > (unsigned int)EVP_MD_size( m_algorithm ) ) {	    std::cout << "derived key too long" << std::endl;	    return SymmetricKey();	}	/*	   2. Apply the underlying hash function Hash for c iterations to the	   concatenation of the password P and the salt S, then extract	   the first dkLen octets to produce a derived key DK:	   T_1 = Hash (P || S) ,	   T_2 = Hash (T_1) ,	   ...	   T_c = Hash (T_{c-1}) ,	   DK = Tc<0..dkLen-1>	*/	// calculate T_1	EVP_DigestUpdate( &m_context, (unsigned char*)secret.data(), secret.size() );	EVP_DigestUpdate( &m_context, (unsigned char*)salt.data(), salt.size() );	SecureArray a( EVP_MD_size( m_algorithm ) );	EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 );	// calculate T_2 up to T_c	for ( unsigned int i = 2; i <= iterationCount; ++i ) {	    EVP_DigestInit( &m_context, m_algorithm );	    EVP_DigestUpdate( &m_context, (unsigned char*)a.data(), a.size() );	    EVP_DigestFinal( &m_context, (unsigned char*)a.data(), 0 );	}	// shrink a to become DK, of the required length	a.resize(keyLength);	/*	   3. Output the derived key DK.	*/	return a;    }protected:    const EVP_MD *m_algorithm;    EVP_MD_CTX m_context;};class opensslPbkdf2Context : public KDFContext{public:    opensslPbkdf2Context(Provider *p, const QString &type) : KDFContext(p, type)    {    }    Provider::Context *clone() const    {	return new opensslPbkdf2Context( *this );    }    SymmetricKey makeKey(const SecureArray &secret, const InitializationVector &salt,			      unsigned int keyLength, unsigned int iterationCount)    {      SecureArray out(keyLength);      PKCS5_PBKDF2_HMAC_SHA1( (char*)secret.data(), secret.size(),			      (unsigned char*)salt.data(), salt.size(),			      iterationCount, keyLength, (unsigned char*)out.data() );      return out;    }protected:};class opensslHMACContext : public MACContext{public:  opensslHMACContext(const EVP_MD *algorithm, Provider *p, const QString &type) : MACContext(p, type)    {	m_algorithm = algorithm;	HMAC_CTX_init( &m_context );    }    void setup(const SymmetricKey &key)    {	HMAC_Init_ex( &m_context, key.data(), key.size(), m_algorithm, 0 );    }    KeyLength keyLength() const    {	return anyKeyLength();    }    void update(const MemoryRegion &a)    {	HMAC_Update( &m_context, (unsigned char *)a.data(), a.size() );    }    void final(MemoryRegion *out)    {	SecureArray sa( EVP_MD_size( m_algorithm ), 0 );	HMAC_Final(&m_context, (unsigned char *)sa.data(), 0 );	HMAC_CTX_cleanup(&m_context);	*out = sa;    }    Provider::Context *clone() const    {	return new opensslHMACContext(*this);    }protected:    HMAC_CTX m_context;    const EVP_MD *m_algorithm;};//----------------------------------------------------------------------------// EVPKey//----------------------------------------------------------------------------// note: this class squelches processing errors, since QCA doesn't care about themclass EVPKey{public:	enum State { Idle, SignActive, SignError, VerifyActive, VerifyError };	EVP_PKEY *pkey;	EVP_MD_CTX mdctx;	State state;	bool raw_type;	SecureArray raw;

⌨️ 快捷键说明

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