📄 security.cxx
字号:
#if ( OPENSSL_VERSION_NUMBER > 0x009060ffL )// const EVP_CIPHER* cipher = EVP_des_ede3_cbc(); const EVP_CIPHER* cipher = EVP_aes_128_cbc(); #else //const EVP_CIPHER* cipher = EVP_enc_null(); EVP_CIPHER* cipher = EVP_des_ede3_cbc();#endif assert( cipher );#if (OPENSSL_VERSION_NUMBER < 0x0090705fL )#warning PKCS7_encrypt() is broken in OpenSSL 0.9.7d#endif PKCS7* pkcs7 = PKCS7_encrypt( certs, in, cipher, flags); if ( !pkcs7 ) { BIO_free(in); BIO_free(out); sk_X509_free(certs); ErrLog( << "Error creating PKCS7 encrypt object" ); //throw Exception("Can't encrypt",__FILE__,__LINE__); return 0; } DebugLog( << "created PKCS7 encrypt object " ); i2d_PKCS7_bio(out,pkcs7); BIO_flush(out); char* outBuf=0; long size = BIO_get_mem_data(out,&outBuf); assert( size > 0 ); Data outData(outBuf,size); assert( (long)outData.size() == size ); InfoLog( << "Encrypted body size is " << outData.size() ); InfoLog( << "Encrypted body is <" << outData.escaped() << ">" ); static char RESIP_ENCRYPT_OUT[] = "resip-encrypt-out"; Security::dumpAsn(RESIP_ENCRYPT_OUT, outData); Pkcs7Contents* outBody = new Pkcs7Contents( outData ); assert( outBody ); outBody->header(h_ContentType).param( p_smimeType ) = "enveloped-data"; outBody->header(h_ContentType).param( p_name ) = "smime.p7m"; outBody->header(h_ContentDisposition).param( p_handling ) = "required"; outBody->header(h_ContentDisposition).param( p_filename ) = "smime.p7"; outBody->header(h_ContentDisposition).value() = "attachment" ; outBody->header(h_ContentTransferEncoding).value() = "binary"; BIO_free(in); BIO_free(out); sk_X509_free(certs); return outBody;}MultipartSignedContents *BaseSecurity::signAndEncrypt( const Data& senderAor, Contents* body, const Data& recipCertName ){ //assert(0); //return 0; return sign(senderAor, encrypt(body, recipCertName));}DataBaseSecurity::computeIdentity( const Data& signerDomain, const Data& in ) const{ DebugLog( << "Compute identity for " << in ); if (mDomainPrivateKeys.count(signerDomain) == 0) { InfoLog( << "No private key for " << signerDomain ); throw Exception("Missing private key when computing identity",__FILE__,__LINE__); } EVP_PKEY* pKey = mDomainPrivateKeys[signerDomain]; assert( pKey ); if ( pKey->type != EVP_PKEY_RSA ) { ErrLog( << "Private key (type=" << pKey->type <<"for " << signerDomain << " is not of type RSA" ); throw Exception("No RSA private key when computing identity",__FILE__,__LINE__); } assert( pKey->type == EVP_PKEY_RSA ); RSA* rsa = EVP_PKEY_get1_RSA(pKey); unsigned char result[4096]; int resultSize = sizeof(result); assert( resultSize >= RSA_size(rsa) ); SHA1Stream sha; sha << in; Data hashRes = sha.getBin(); DebugLog( << "hash of string is 0x" << hashRes.hex() );#if 1 int r = RSA_sign(NID_sha1, (unsigned char *)hashRes.data(), hashRes.size(), result, (unsigned int*)( &resultSize ), rsa); assert( r == 1 );#else resultSize = RSA_private_encrypt(hashResLen, hashRes, result, rsa, RSA_PKCS1_PADDING); if ( resultSize == -1 ) { DebugLog( << "Problem doing RSA encrypt for identity"); while (1) { const char* file; int line; unsigned long code = ERR_get_error_line(&file,&line); if ( code == 0 ) { break; } char buf[256]; ERR_error_string_n(code,buf,sizeof(buf)); ErrLog( << buf ); InfoLog( << "Error code = " << code << " file="<<file<<" line=" << line ); } return Data::Empty; }#endif Data res(result,resultSize); DebugLog( << "rsa encrypt of hash is 0x"<< res.hex() ); Data enc = res.base64encode(); static char IDENTITY_IN[] = "identity-in"; static char IDENTITY_IN_HASH[] = "identity-in-hash"; static char IDENTITY_IN_RSA[] = "identity-in-rsa"; static char IDENTITY_IN_BASE64[] = "identity-in-base64"; Security::dumpAsn(IDENTITY_IN, in ); Security::dumpAsn(IDENTITY_IN_HASH, hashRes ); Security::dumpAsn(IDENTITY_IN_RSA,res); Security::dumpAsn(IDENTITY_IN_BASE64,enc); return enc;}boolBaseSecurity::checkIdentity( const Data& signerDomain, const Data& in, const Data& sigBase64, X509* pCert ) const{ X509* cert = pCert; if (!cert) { if (mDomainCerts.count(signerDomain) == 0) { ErrLog( << "No public key for " << signerDomain ); throw Exception("Missing public key when verifying identity",__FILE__,__LINE__); } cert = mDomainCerts[signerDomain]; } DebugLog( << "Check identity for " << in ); DebugLog( << " base64 data is " << sigBase64 ); Data sig = sigBase64.base64decode(); DebugLog( << "decoded sig is 0x"<< sig.hex() ); SHA1Stream sha; sha << in; Data hashRes = sha.getBin(); DebugLog( << "hash of string is 0x" << hashRes.hex() ); EVP_PKEY* pKey = X509_get_pubkey( cert ); assert( pKey ); assert( pKey->type == EVP_PKEY_RSA ); RSA* rsa = EVP_PKEY_get1_RSA(pKey);#if 1 int ret = RSA_verify(NID_sha1, (unsigned char *)hashRes.data(), hashRes.size(), (unsigned char*)sig.data(), sig.size(), rsa);#else unsigned char result[4096]; int resultSize = sizeof(result); assert( resultSize >= RSA_size(rsa) ); resultSize = RSA_public_decrypt(sig.size(),(unsigned char*)sig.data(), result, rsa, RSA_PKCS1_PADDING ); assert( resultSize != -1 ); //assert( resultSize == SHA_DIGEST_LENGTH ); Data recievedHash(result,resultSize); dumpAsn("identity-out-decrypt", recievedHash ); bool ret = ( computedHash == recievedHash );#endif DebugLog( << "rsa verify result is " << ret ); static char IDENTITY_OUT_MSG[] = "identity-out-msg"; static char IDENTITY_OUT_BASE64[] = "identity-out-base64"; static char IDENTITY_OUT_SIG[] = "identity-out-sig"; static char IDENTITY_OUT_HASH[] = "identity-out-hash"; Security::dumpAsn(IDENTITY_OUT_MSG, in ); Security::dumpAsn(IDENTITY_OUT_BASE64,sigBase64); Security::dumpAsn(IDENTITY_OUT_SIG, sig); Security::dumpAsn(IDENTITY_OUT_HASH, hashRes ); return (ret != 0);}voidBaseSecurity::checkAndSetIdentity( const SipMessage& msg, const Data& certDer) const{ auto_ptr<SecurityAttributes> sec(new SecurityAttributes); X509* cert=NULL; try { if ( !certDer.empty() ) {#if (OPENSSL_VERSION_NUMBER < 0x0090800fL ) unsigned char* in = (unsigned char*)certDer.data();#else unsigned const char* in = (unsigned const char*)certDer.data();#endif if (d2i_X509(&cert,&in,certDer.size()) == 0) { DebugLog(<< "Could not read DER certificate from " << certDer ); cert = NULL; } } if ( certDer.empty() || cert ) { if ( checkIdentity(msg.header(h_From).uri().host(), msg.getCanonicalIdentityString(), msg.header(h_Identity).value(), cert ) ) { sec->setIdentity(msg.header(h_From).uri().getAor()); sec->setIdentityStrength(SecurityAttributes::Identity); } else { sec->setIdentity(msg.header(h_From).uri().getAor()); sec->setIdentityStrength(SecurityAttributes::FailedIdentity); } } else { sec->setIdentity(msg.header(h_From).uri().getAor()); sec->setIdentityStrength(SecurityAttributes::FailedIdentity); } } catch (BaseException& e) { ErrLog(<<"Caught exception: "<< e); sec->setIdentity(msg.header(h_From).uri().getAor()); sec->setIdentityStrength(SecurityAttributes::FailedIdentity); } msg.setSecurityAttributes(sec);}Contents*BaseSecurity::decrypt( const Data& decryptorAor, const Pkcs7Contents* contents){ DebugLog( << "decryptor Aor: <" << decryptorAor << ">" ); int flags=0; flags |= PKCS7_BINARY; // for now, assume that this is only a singed message assert( contents ); Data text = contents->getBodyData(); DebugLog( << "uncode body = <" << text.escaped() << ">" ); DebugLog( << "uncode body size = " << text.size() ); static char RESIP_ASN_DECRYPT[] = "resip-asn-decrypt"; Security::dumpAsn(RESIP_ASN_DECRYPT, text ); BIO* in = BIO_new_mem_buf( (void*)text.c_str(), text.size()); assert(in); InfoLog( << "created in BIO"); BIO* out; out = BIO_new(BIO_s_mem()); assert(out); InfoLog( << "created out BIO" ); PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0); if ( !pkcs7 ) { ErrLog( << "Problems doing decode of PKCS7 object" ); while (1) { const char* file; int line; unsigned long code = ERR_get_error_line(&file,&line); if ( code == 0 ) { break; } char buf[256]; ERR_error_string_n(code,buf,sizeof(buf)); ErrLog( << buf ); InfoLog( << "Error code = " << code << " file=" << file << " line=" << line ); } BIO_free(in); BIO_free(out); return 0; } BIO_flush(in); int type=OBJ_obj2nid(pkcs7->type); switch (type) { case NID_pkcs7_signed: InfoLog( << "data is pkcs7 signed" ); break; case NID_pkcs7_signedAndEnveloped: InfoLog( << "data is pkcs7 signed and enveloped" ); break; case NID_pkcs7_enveloped: InfoLog( << "data is pkcs7 enveloped" ); break; case NID_pkcs7_data: InfoLog( << "data i pkcs7 data" ); break; case NID_pkcs7_encrypted: InfoLog( << "data is pkcs7 encrypted " ); break; case NID_pkcs7_digest: InfoLog( << "data is pkcs7 digest" ); break; default: InfoLog( << "Unkown pkcs7 type" ); break; } STACK_OF(X509)* certs = sk_X509_new_null(); assert( certs ); // flags |= PKCS7_NOVERIFY; assert( mRootTlsCerts ); switch (type) { case NID_pkcs7_signedAndEnveloped: { BIO_free(in); BIO_free(out); sk_X509_free(certs); throw Exception("Signed and enveloped is not supported", __FILE__, __LINE__); } break; case NID_pkcs7_enveloped: { if (mUserPrivateKeys.count(decryptorAor) == 0) { BIO_free(in); BIO_free(out); sk_X509_free(certs); InfoLog( << "Don't have a private key for " << decryptorAor << " for PKCS7_decrypt" ); throw Exception("Missing private key", __FILE__, __LINE__); } else if (mUserCerts.count(decryptorAor) == 0) { BIO_free(in); BIO_free(out); sk_X509_free(certs); InfoLog( << "Don't have a public cert for " << decryptorAor << " for PKCS7_decrypt" ); throw Exception("Missing cert", __FILE__, __LINE__); } EVP_PKEY* privateKey = mUserPrivateKeys[decryptorAor]; X509* publicCert = mUserCerts[decryptorAor]; if ( PKCS7_decrypt(pkcs7, privateKey, publicCert, out, flags ) != 1 ) { ErrLog( << "Problems doing PKCS7_decrypt" ); while (1) { const char* file; int line; unsigned long code = ERR_get_error_line(&file,&line); if ( code == 0 ) { break; } char buf[256]; ERR_error_string_n(code,buf,sizeof(buf)); ErrLog( << buf ); InfoLog( << "Error code = " << code << " file=" << file << " line=" << line ); } BIO_free(in); BIO_free(out); sk_X509_free(certs); return 0; } } break; default: BIO_free(in); BIO_free(out); sk_X509_free(certs); ErrLog(<< "Got PKCS7 data that could not be handled type=" << type ); throw Exception("Unsupported PKCS7 data type", __FILE__, __LINE__); } BIO_flush(out); BUF_MEM* bufMem; BIO_get_mem_ptr(out, &bufMem); int len = bufMem->length; char* buffer = new char[len]; memcpy(buffer, bufMem->data, len); BIO_set_close(out, BIO_CLOSE); BIO_free(in); BIO_free(out); sk_X509_free(certs); // parse out the header information and form new body. // TODO !jf! this is a really crappy parser - shoudl do proper mime stuff ParseBuffer pb(buffer, len); const char* headerStart = pb.position(); // pull out contents type only pb.skipToChars("Content-Type"); pb.assertNotEof(); pb.skipToChar(Symbols::COLON[0]); pb.skipChar(); pb.assertNotEof(); pb.skipWhitespace(); const char* typeStart = pb.position(); pb.assertNotEof(); // determine contents-type header buffer pb.skipToTermCRLF(); pb.assertNotEof(); ParseBuffer subPb(typeStart, pb.position() - typeStart); Mime contentType; contentType.parse(subPb); pb.assertNotEof(); // determine body start pb.reset(typeStart); const char* bodyStart = pb.skipToChars(Symbols::CRLFCRLF); pb.assertNotEof(); bodyStart += 4; // determine contents body buffer pb.skipToEnd(); Data tmp; pb.data(tmp, bodyStart); // create contents against body Contents* ret = Contents::createContents(contentType, tmp); ret->addBuffer(buffer); // pre-parse headers ParseBuffer headersPb(headerStart, bodyStart-4-headerStart); ret->preParseHeaders(headersPb); InfoLog( << "Got body data of " << ret->getBodyData() ); return ret;}Contents*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -