From 38bbfd9677fac0845e903abd200de1119b5558ee Mon Sep 17 00:00:00 2001 From: Paul Howarth Date: May 25 2012 13:55:03 +0000 Subject: Fix insecure ElGamal key generation (#825165, CVE-2012-2417) - Fix LP#985164: insecure ElGamal key generation (#825165, CVE-2012-2417) - Update URL - Fix shellbangs and permissions of installed files --- diff --git a/.gitignore b/.gitignore index bc34bf7..0452e1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -pycrypto-2.0.1.tar.gz -/pycrypto-2.0.1-hobbled.tar.gz +/pycrypto-[0-9.-]*.tar.gz diff --git a/pycrypto-2.0.1-CVE-2012-2417.patch b/pycrypto-2.0.1-CVE-2012-2417.patch new file mode 100644 index 0000000..364caa7 --- /dev/null +++ b/pycrypto-2.0.1-CVE-2012-2417.patch @@ -0,0 +1,90 @@ +--- PublicKey/ElGamal.py ++++ PublicKey/ElGamal.py +@@ -25,39 +25,54 @@ + Generate an ElGamal key of length 'bits', using 'randfunc' to get + random data and 'progress_func', if present, to display + the progress of the key generation. ++ ++ The key will be safe for use for both encryption and signature ++ (although it should be used for **only one** purpose). ++ + """ + obj=ElGamalobj() +- # Generate prime p ++ # Generate a safe prime p ++ # See Algorithm 4.86 in Handbook of Applied Cryptography + if progress_func: + progress_func('p\n') +- obj.p=bignum(getPrime(bits, randfunc)) +- # Generate random number g ++ while 1: ++ q = bignum(getPrime(bits-1, randfunc)) ++ obj.p = 2*q+1 ++ if number.isPrime(obj.p, randfunc=randfunc): ++ break ++ # Generate generator g ++ # See Algorithm 4.80 in Handbook of Applied Cryptography ++ # Note that the order of the group is n=p-1=2q, where q is prime + if progress_func: + progress_func('g\n') +- size=bits-1-(ord(randfunc(1)) & 63) # g will be from 1--64 bits smaller than p +- if size<1: +- size=bits-1 +- while (1): +- obj.g=bignum(getPrime(size, randfunc)) +- if obj.g < obj.p: ++ while 1: ++ # We must avoid g=2 because of Bleichenbacher's attack described ++ # in "Generating ElGamal signatures without knowning the secret key", ++ # 1996 ++ # ++ obj.g = number.getRandomRange(3, obj.p, randfunc) ++ safe = 1 ++ if pow(obj.g, 2, obj.p)==1: ++ safe=0 ++ if safe and pow(obj.g, q, obj.p)==1: ++ safe=0 ++ # Discard g if it divides p-1 because of the attack described ++ # in Note 11.67 (iii) in HAC ++ if safe and divmod(obj.p-1, obj.g)[1]==0: ++ safe=0 ++ # g^{-1} must not divide p-1 because of Khadir's attack ++ # described in "Conditions of the generator for forging ElGamal ++ # signature", 2011 ++ ginv = number.inverse(obj.g, obj.p) ++ if safe and divmod(obj.p-1, ginv)[1]==0: ++ safe=0 ++ if safe: + break +- size=(size+1) % bits +- if size==0: +- size=4 +- # Generate random number x ++ # Generate private key x + if progress_func: + progress_func('x\n') +- while (1): +- size=bits-1-ord(randfunc(1)) # x will be from 1 to 256 bits smaller than p +- if size>2: +- break +- while (1): +- obj.x=bignum(getPrime(size, randfunc)) +- if obj.x < obj.p: +- break +- size = (size+1) % bits +- if size==0: +- size=4 ++ obj.x=number.getRandomRange(2, obj.p-1, randfunc) ++ # Generate public key y + if progress_func: + progress_func('y\n') + obj.y = pow(obj.g, obj.x, obj.p) +@@ -105,6 +120,8 @@ + return (a, b) + + def _verify(self, M, sig): ++ if sig[0]<1 or sig[0]>p-1: ++ return 0 + v1=pow(self.y, sig[0], self.p) + v1=(v1*pow(sig[0], sig[1], self.p)) % self.p + v2=pow(self.g, M, self.p) diff --git a/python-crypto.spec b/python-crypto.spec index de3804e..a27dfe6 100644 --- a/python-crypto.spec +++ b/python-crypto.spec @@ -4,10 +4,10 @@ Summary: Cryptography library for Python Name: python-crypto Version: 2.0.1 -Release: 4%{?dist}.2 +Release: 5%{?dist} License: Public Domain Group: Development/Libraries -URL: http://www.amk.ca/python/code/crypto.html +URL: http://www.pycrypto.org/ # The original tarball: # http://www.amk.ca/files/python/crypto/pycrypto-2.0.1.tar.gz @@ -18,10 +18,14 @@ Source: pycrypto-2.0.1-hobbled.tar.gz # patch taken from # http://gitweb2.dlitz.net/?p=crypto/pycrypto-2.x.git;a=commitdiff;h=d1c4875e1f220652fe7ff8358f56dee3b2aba31b -Patch0: %{name}-fix_buffer_overflow.patch +Patch0: %{name}-fix_buffer_overflow.patch # Remove references to IDEA and RC5: -Patch1: python-crypto-hobble.patch +Patch1: python-crypto-hobble.patch + +# Backport to pycrypto 2.0.1 of: +# https://github.com/Legrandin/pycrypto/commit/9f912f13df99ad3421eff360d6a62d7dbec755c2 +Patch2: pycrypto-2.0.1-CVE-2012-2417.patch BuildRequires: python >= 2.2 BuildRequires: python-devel >= 2.2 @@ -38,19 +42,29 @@ SHA), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.). %prep %setup -n pycrypto-%{version} -q -sed -i s:/lib:/%_lib:g setup.py + +# C source should not be executable +find . -name '*.c' | xargs chmod -c -x + +# Remove redundant shellbang +sed -i -e '/#!\/usr\/local\/bin\/python/d' Util/RFC1751.py + +# Fix setup.py for lib64 if necessary +sed -i -e 's|/lib|/%_lib|g' setup.py + %patch0 -b .patch0 -p1 %patch1 -p1 +%patch2 %build CFLAGS="$RPM_OPT_FLAGS" %{__python} setup.py build - %install rm -rf $RPM_BUILD_ROOT %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT -find -name "*.py"|xargs %{__perl} -pi -e "s:/usr/local/bin/python:%{__python}:" +# Remove group write permissions on shared objects +find %{buildroot}%{python_sitearch} -name '*.so' -exec chmod -c g-w {} \; %check %{__python} test.py @@ -81,15 +95,20 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Fri May 25 2012 Paul Howarth - 2.0.1-5 +- Fix LP#985164: insecure ElGamal key generation (#825165, CVE-2012-2417) +- Update URL +- Fix shellbangs and permissions of installed files + * Wed Sep 22 2010 David Malcolm - 2.0.1-4.2 - remove IDEA and RC5 implementations - add %%check section * Fri Feb 13 2009 Thorsten Leemhuis - 2.0.1-4.1 - some improvements from fedora branch --- add patch to fix #485298 / CVE-2009-0544 --- provide pycrypto --- drop patch0 and fix libdir handling so it works on more arches than x86_64 + - add patch to fix #485298 / CVE-2009-0544 + - provide pycrypto + - drop patch0 and fix libdir handling so it works on more arches than x86_64 * Thu Sep 07 2006 Thorsten Leemhuis - 2.0.1-4 - Don't ghost pyo files (#205408)