wbond / oscrypto

Compiler-free Python crypto library backed by the OS, supporting CPython and PyPy
MIT License
320 stars 70 forks source link

OSX Error decoding fails with incorrect pub key #17

Closed doc-hex closed 7 years ago

doc-hex commented 7 years ago

When constructing an EC public key from invalid X, Y coordinates (ie. not on the curve), the error handling code in oscrypto/_osx/_core_foundation.py fails due to a NULL c-pointer. Root cause is expecting CFHelpers.cf_string_to_unicode to return None if given a null CFStringRef. It seems to raise an exception instead:

...
  File ".../ENV/lib/python3.5/site-packages/oscrypto/_osx/_core_foundation.py", line 43, in handle_cf_error
    output = CFHelpers.cf_string_to_unicode(cf_string_ref)
  File ".../ENV/lib/python3.5/site-packages/oscrypto/_osx/_core_foundation_cffi.py", line 248, in cf_string_to_unicode
    string = ffi.string(string_ptr)
  File ".../ENV/lib/python3.5/site-packages/cffi/api.py", line 300, in string
    return self._backend.string(cdata, maxlen)
RuntimeError: cannot use string() on <cdata 'char *' NULL>

Here is a snippet of code that demonstrates the issue:

from oscrypto import asymmetric
from binascii import a2b_hex, b2a_hex
from asn1crypto.keys import PublicKeyInfo, PublicKeyAlgorithmId, PublicKeyAlgorithm
from asn1crypto.keys import ECPointBitString, NamedCurve

def test_it():
    if 0:
        pub_key, _ = asymmetric.generate_pair('ec', curve=u'secp256r1')
        x,y = pub_key.asn1['public_key'].to_coords()
    else:
        x, y = 123, 456

    algo = PublicKeyAlgorithm()
    algo['algorithm'] = PublicKeyAlgorithmId('ec')
    algo['parameters'] = NamedCurve('secp256r1')

    pubkey = PublicKeyInfo()
    pubkey['algorithm'] = algo
    pubkey['public_key'] = ECPointBitString.from_coords(x, y)

    pub_key2 = asymmetric.load_public_key(pubkey.dump())

I've already patched my copy of this code to catch and handle this specific case, but I wanted to report it anyway. The remainder of the error handling code works and give "Invalid Key" for this case, which seems appropriate.

Here are some version numbers from my machine:

Darwin x.local 15.6.0 Darwin Kernel Version 15.6.0: Mon Aug 29 20:21:34 PDT 2016; root:xnu-3248.60.11~1/RELEASE_X86_64 x86_64

asn1crypto==0.19.0
certbuilder==0.14.2
cffi==1.9.1
idna==2.2
oscrypto==0.17.2
pyasn1==0.1.9
pycparser==2.17
six==1.10.0
wbond commented 7 years ago

This should be fixed by 431417752f98d3899ef6386da228bc53630fb7aa, which will be part of the next release