--- a/components/openstack/heat/patches/04-nopycrypto.patch Fri Feb 05 11:09:10 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-In-house removal of PyCrypto dependency in Heat. This patch is
-Solaris-specific and not suitable for upstream.
-
---- heat-2014.2.2/heat/common/crypt.py.~1~ 2014-12-04 21:02:27.000000000 -0800
-+++ heat-2014.2.2/heat/common/crypt.py 2015-01-31 16:56:20.917251751 -0800
-@@ -13,7 +13,7 @@
-
- import base64
-
--from Crypto.Cipher import AES
-+from M2Crypto.EVP import Cipher
- from oslo.config import cfg
-
- from heat.openstack.common.crypto import utils
-@@ -57,7 +57,9 @@ def heat_decrypt(auth_info):
- if auth_info is None:
- return None
- auth = base64.b64decode(auth_info)
-- iv = auth[:AES.block_size]
-- cipher = AES.new(cfg.CONF.auth_encryption_key[:32], AES.MODE_CFB, iv)
-- res = cipher.decrypt(auth[AES.block_size:])
-+ iv = auth[:16]
-+ cipher = Cipher(alg='aes_256_cfb', key=cfg.CONF.auth_encryption_key[:32],
-+ iv=iv, op=0)
-+ padded = cipher.update(auth[16:])
-+ res = padded + cipher.final()
- return res
---- heat-2014.2.2/heat/openstack/common/crypto/utils.py.~1~ 2014-12-04 21:02:30.000000000 -0800
-+++ heat-2014.2.2/heat/openstack/common/crypto/utils.py 2015-01-31 16:56:20.917680985 -0800
-@@ -14,8 +14,8 @@
-
- import base64
-
--from Crypto.Hash import HMAC
--from Crypto import Random
-+from M2Crypto import EVP
-+from M2Crypto import Rand
- import six
-
- from heat.openstack.common.gettextutils import _
-@@ -23,6 +23,24 @@ from heat.openstack.common import import
-
- bchr = six.int2byte
-
-+# Provide a mapping between the names of hash types used by PyCrypto to
-+# their digest sizes and the corresponding algorithm name used by
-+# M2Crypto/OpenSSL.
-+hashmap = {
-+ 'SHA224': (28, 'sha224'),
-+ 'SHA256': (32, 'sha256'),
-+ 'SHA384': (48, 'sha384'),
-+ 'SHA512': (64, 'sha512')
-+}
-+
-+# Provide a mapping between the length of a key and the algorithm name
-+# used by M2Crypto/OpenSSL.
-+algomap = {
-+ 16: 'aes_128_cbc',
-+ 24: 'aes_192_cbc',
-+ 32: 'aes_256_cbc'
-+}
-+
-
- class CryptoutilsException(Exception):
- """Generic Exception for Crypto utilities."""
-@@ -39,6 +57,33 @@ class CipherBlockLengthTooBig(Cryptoutil
- super(CryptoutilsException, self).__init__(message)
-
-
-+class CipherKeyLengthInvalid(CryptoutilsException):
-+ """The encryption key length is invalid for AES-CBC."""
-+
-+ def __init__(self, keylen):
-+ msg = _("Encryption key length of %d is invalid for AES-CBC.")
-+ message = msg % keylen
-+ super(CryptoutilsException, self).__init__(message)
-+
-+
-+class CipherTypeNotSupported(CryptoutilsException):
-+ """The encryption cipher type is not supported."""
-+
-+ def __init__(self, enctype):
-+ msg = _("Encryption cipher type %s is not supported")
-+ message = msg % enctype
-+ super(CryptoutilsException, self).__init__(message)
-+
-+
-+class HashTypeNotSupported(CryptoutilsException):
-+ """The message authentication hash function is not supported."""
-+
-+ def __init__(self, hashtype):
-+ msg = _("Message authentication hash function %s is not supported")
-+ message = msg % hashtype
-+ super(CryptoutilsException, self).__init__(message)
-+
-+
- class HKDFOutputLengthTooLong(CryptoutilsException):
- """The amount of Key Material asked is too much."""
-
-@@ -55,8 +100,10 @@ class HKDF(object):
- """
-
- def __init__(self, hashtype='SHA256'):
-- self.hashfn = importutils.import_module('Crypto.Hash.' + hashtype)
-- self.max_okm_length = 255 * self.hashfn.digest_size
-+ if hashtype not in hashmap:
-+ raise HashTypeNotSupported(hashtype)
-+ (self.digest_size, self.algo) = hashmap[hashtype]
-+ self.max_okm_length = 255 * self.digest_size
-
- def extract(self, ikm, salt=None):
- """An extract function that can be used to derive a robust key given
-@@ -67,9 +114,9 @@ class HKDF(object):
- :param salt: optional salt value (a non-secret random value)
- """
- if salt is None:
-- salt = b'\x00' * self.hashfn.digest_size
-+ salt = b'\x00' * self.digest_size
-
-- return HMAC.new(salt, ikm, self.hashfn).digest()
-+ return EVP.hmac(salt, ikm, self.algo)
-
- def expand(self, prk, info, length):
- """An expand function that will return arbitrary length output that can
-@@ -83,12 +130,12 @@ class HKDF(object):
- if length > self.max_okm_length:
- raise HKDFOutputLengthTooLong(length, self.max_okm_length)
-
-- N = (length + self.hashfn.digest_size - 1) // self.hashfn.digest_size
-+ N = (length + self.digest_size - 1) // self.digest_size
-
- okm = b""
- tmp = b""
- for block in range(1, N + 1):
-- tmp = HMAC.new(prk, tmp + info + bchr(block), self.hashfn).digest()
-+ tmp = EVP.hmac(prk, tmp + info + bchr(block), self.algo)
- okm += tmp
-
- return okm[:length]
-@@ -108,11 +155,15 @@ class SymmetricCrypto(object):
- """
-
- def __init__(self, enctype='AES', hashtype='SHA256'):
-- self.cipher = importutils.import_module('Crypto.Cipher.' + enctype)
-- self.hashfn = importutils.import_module('Crypto.Hash.' + hashtype)
-+ if enctype != 'AES':
-+ raise CipherTypeNotSupported(enctype)
-+ if hashtype not in hashmap:
-+ raise HashTypeNotSupported(hashtype)
-+ self.algo = hashmap[hashtype][1]
-+ self.block_size = 16
-
- def new_key(self, size):
-- return Random.new().read(size)
-+ return Rand.rand_bytes(size)
-
- def encrypt(self, key, msg, b64encode=True):
- """Encrypt the provided msg and returns the cyphertext optionally
-@@ -129,19 +180,14 @@ class SymmetricCrypto(object):
-
- :returns enc: a block of encrypted data.
- """
-- iv = Random.new().read(self.cipher.block_size)
-- cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv)
--
-- # CBC mode requires a fixed block size. Append padding and length of
-- # padding.
-- if self.cipher.block_size > MAX_CB_SIZE:
-- raise CipherBlockLengthTooBig(self.cipher.block_size, MAX_CB_SIZE)
-- r = len(msg) % self.cipher.block_size
-- padlen = self.cipher.block_size - r - 1
-- msg += b'\x00' * padlen
-- msg += bchr(padlen)
-+ keylen = len(key)
-+ if keylen not in algomap:
-+ raise CipherKeyLengthInvalid(keylen)
-+ iv = Rand.rand_bytes(self.block_size)
-+ cipher = EVP.Cipher(algomap[keylen], key, iv, 1)
-
-- enc = iv + cipher.encrypt(msg)
-+ enc = iv + cipher.update(msg)
-+ enc += cipher.final()
- if b64encode:
- enc = base64.b64encode(enc)
- return enc
-@@ -157,14 +203,16 @@ class SymmetricCrypto(object):
-
- :returns plain: the plaintext message.
- """
-+ keylen = len(key)
-+ if keylen not in algomap:
-+ raise CipherKeyLengthInvalid(keylen)
- if b64decode:
- msg = base64.b64decode(msg)
-- iv = msg[:self.cipher.block_size]
-- cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv)
-+ iv = msg[:self.block_size]
-+ cipher = EVP.Cipher(algomap[keylen], key, iv, 0)
-
-- padded = cipher.decrypt(msg[self.cipher.block_size:])
-- l = ord(padded[-1:]) + 1
-- plain = padded[:-l]
-+ padded = cipher.update(msg[self.block_size:])
-+ plain = padded + cipher.final()
- return plain
-
- def sign(self, key, msg, b64encode=True):
-@@ -177,8 +225,7 @@ class SymmetricCrypto(object):
-
- :returns out: a base64 encoded signature.
- """
-- h = HMAC.new(key, msg, self.hashfn)
-- out = h.digest()
-+ out = EVP.hmac(key, msg, self.algo)
- if b64encode:
- out = base64.b64encode(out)
- return out