mirror of
https://github.com/textmate/textmate.git
synced 2026-04-06 03:01:29 -04:00
Use Security framework instead of deprecated OpenSSL functions
This commit is contained in:
@@ -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 ()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ¶ms, 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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user