Use Security framework instead of deprecated OpenSSL functions

This commit is contained in:
jtbandes
2012-08-11 19:49:50 -07:00
parent 4cc010c289
commit 3d3d22f509
4 changed files with 69 additions and 48 deletions

View File

@@ -1,17 +1,27 @@
#include "filter_check_signature.h"
#include <cf/cf.h>
#include <text/decode.h>
#include <text/format.h>
#include <oak/debug.h>
namespace network
{
check_signature_t::check_signature_t (key_chain_t const& keyChain, std::string const& signeeHeader, std::string const& signatureHeader) : _key_chain(keyChain), _signee_header(signeeHeader), _signature_header(signatureHeader)
check_signature_t::check_signature_t (key_chain_t const& keyChain, std::string const& signeeHeader, std::string const& signatureHeader) : _key_chain(keyChain), _signee_header(signeeHeader), _signature_header(signatureHeader), _data(NULL)
{
}
check_signature_t::~check_signature_t ()
{
if(_data)
CFRelease(_data);
}
bool check_signature_t::setup ()
{
return EVP_VerifyInit(&ctx, EVP_dss1()) == 1;
if(_data)
CFRelease(_data);
return _data = CFDataCreateMutable(NULL, 0);
}
bool check_signature_t::receive_header (std::string const& header, std::string const& value)
@@ -25,7 +35,8 @@ namespace network
bool check_signature_t::receive_data (char const* buf, size_t len)
{
return EVP_VerifyUpdate(&ctx, buf, len) == 1;
CFDataAppendBytes(_data, (const UInt8*)buf, len);
return true;
}
bool check_signature_t::receive_end (std::string& error)
@@ -34,21 +45,39 @@ namespace network
return (error = "Missing signee."), false;
if(_signature == NULL_STR)
return (error = "Missing signature."), false;
bool res = false;
if(key_chain_t::key_ptr key = _key_chain.find(_signee))
{
std::string signature = decode::base64(_signature);
if(EVP_VerifyFinal(&ctx, (unsigned char*)&signature[0], signature.size(), *key) == 1)
return true;
error = text::format("Bad signature.");
CFErrorRef err = NULL;
CFDataRef sig_data = CFDataCreateWithBytesNoCopy(NULL, (const UInt8*)signature.data(), signature.size(), kCFAllocatorNull);
if(SecTransformRef verifier = SecVerifyTransformCreate(*key, sig_data, &err))
{
if(SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, _data, &err))
{
res = SecTransformExecute(verifier, &err) == kCFBooleanTrue;
if(!res)
error = text::format("Bad signature.");
}
else
error = text::format("Error setting transform input: %s.", cf::to_s(err).c_str());
CFRelease(verifier);
}
else
error = text::format("Error creating verify transform: %s.", cf::to_s(err).c_str());
if(sig_data)
CFRelease(sig_data);
}
else
{
error = text::format("Unknown signee: %s.", _signee.c_str());
}
return false;
return res;
}
std::string check_signature_t::name ()

View File

@@ -13,6 +13,7 @@ namespace network
struct PUBLIC check_signature_t : filter_t
{
check_signature_t (key_chain_t const& keyChain, std::string const& signeeHeader, std::string const& signatureHeader);
~check_signature_t ();
bool setup ();
bool receive_header (std::string const& header, std::string const& value);
@@ -29,7 +30,7 @@ namespace network
std::string const _signee_header;
std::string const _signature_header;
EVP_MD_CTX ctx;
CFMutableDataRef _data;
std::string _signee = NULL_STR;
std::string _signature = NULL_STR;

View File

@@ -1,4 +1,5 @@
#include "key_chain.h"
#include <cf/cf.h>
#include <oak/oak.h>
#include <plist/plist.h>
@@ -19,57 +20,49 @@ key_chain_t::key_t::~key_t ()
void key_chain_t::key_t::init () const
{
_ssl_key = NULL;
_ssl_bio = NULL;
_ssl_data = NULL;
_sec_key = NULL;
}
bool key_chain_t::key_t::setup () const
{
if(_ssl_key)
if(_sec_key)
return true;
bool res = false;
if(_ssl_key = EVP_PKEY_new())
SecItemImportExportKeyParameters params = { .keyUsage = NULL, .keyAttributes = NULL };
SecExternalItemType type = kSecItemTypePublicKey;
SecExternalFormat format = kSecFormatPEMSequence;
CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, (const UInt8*)_key_data.data(), _key_data.size(), kCFAllocatorNull);
CFArrayRef items = NULL;
OSStatus err;
if(err = SecItemImport(data, NULL, &type, &format, 0, &params, NULL, &items) == errSecSuccess)
{
if(_ssl_bio = BIO_new_mem_buf((char*)_key_data.data(), _key_data.size()))
_sec_key = (SecKeyRef)CFArrayGetValueAtIndex(items, 0);
if(_sec_key != NULL)
{
if(_ssl_data = PEM_read_bio_DSA_PUBKEY(_ssl_bio, NULL, NULL, NULL))
{
if(res = EVP_PKEY_assign_DSA(_ssl_key, _ssl_data) == 1)
_ssl_data = NULL;
}
else
{
fprintf(stderr, "*** error reading key\n");
}
}
else
{
fprintf(stderr, "*** error creating BIO\n");
CFRetain(_sec_key);
res = true;
}
CFRelease(items);
}
else
{
fprintf(stderr, "*** error creating PKEY\n");
CFStringRef message = SecCopyErrorMessageString(err, NULL);
fprintf(stderr, "*** error importing key: %s\n", cf::to_s(message).c_str());
CFRelease(message);
}
if(!res)
cleanup();
CFRelease(data);
return res;
}
void key_chain_t::key_t::cleanup () const
{
if(_ssl_data)
DSA_free(_ssl_data);
if(_ssl_bio)
BIO_free(_ssl_bio);
if(_ssl_key)
EVP_PKEY_free(_ssl_key);
if(_sec_key)
CFRelease(_sec_key);
init();
}

View File

@@ -20,7 +20,7 @@ struct PUBLIC key_chain_t
std::string const& identity () const { return _identity; }
std::string const& name () const { return _name; }
operator EVP_PKEY* () const { setup(); return _ssl_key; }
operator SecKeyRef () const { setup(); return _sec_key; }
private:
friend struct key_chain_t;
@@ -28,9 +28,7 @@ struct PUBLIC key_chain_t
std::string _name;
std::string _key_data;
mutable EVP_PKEY* _ssl_key;
mutable BIO* _ssl_bio;
mutable DSA* _ssl_data;
mutable SecKeyRef _sec_key;
void init () const;
bool setup () const;