📄 security.cxx
字号:
Data bodyData;
DataStream strm(bodyData);
bodyIn->encodeHeaders(strm);
bodyIn->encode( strm );
strm.flush();
InfoLog( << "body data to encrypt is <" << bodyData.escaped() << ">" );
const char* p = bodyData.data();
int s = bodyData.size();
BIO* in = BIO_new_mem_buf( (void*)p,s);
assert(in);
DebugLog( << "created in BIO");
BIO* out = BIO_new(BIO_s_mem());
assert(out);
DebugLog( << "created out BIO" );
InfoLog( << "target cert name is <" << recipCertName << ">" );
if (mUserCerts.count(recipCertName) == 0)
{
BIO_free(in);
BIO_free(out);
WarningLog (<< "Tried to encrypt with no cert or private key for " << recipCertName);
throw Exception("No cert or private key to encrypt with",__FILE__,__LINE__);
}
X509* cert = mUserCerts[recipCertName];
assert(cert);
STACK_OF(X509) *certs = sk_X509_new_null();
assert(certs);
sk_X509_push(certs, cert);
// if you think you need to change the following few lines, please email fluffy
// the value of OPENSSL_VERSION_NUMBER ( in opensslv.h ) and the signature of
// PKCS_encrypt found ( in pkcs7.h ) and the OS you are using
#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));
}
Data
BaseSecurity::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;
}
bool
BaseSecurity::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);
}
void
BaseSecurity::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&)
{
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -