PageRenderTime 165ms CodeModel.GetById 32ms RepoModel.GetById 8ms app.codeStats 0ms

/code/default/python27/1.0/lib/linux/cryptography/hazmat/backends/commoncrypto/backend.py

https://gitlab.com/Mirros/XX-net
Python | 244 lines | 205 code | 27 blank | 12 comment | 13 complexity | 25775ec111a046c632f825cc9a443ef2 MD5 | raw file
  1. # This file is dual licensed under the terms of the Apache License, Version
  2. # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3. # for complete details.
  4. from __future__ import absolute_import, division, print_function
  5. from collections import namedtuple
  6. from cryptography import utils
  7. from cryptography.exceptions import InternalError
  8. from cryptography.hazmat.backends.commoncrypto.ciphers import (
  9. _CipherContext, _GCMCipherContext
  10. )
  11. from cryptography.hazmat.backends.commoncrypto.hashes import _HashContext
  12. from cryptography.hazmat.backends.commoncrypto.hmac import _HMACContext
  13. from cryptography.hazmat.backends.interfaces import (
  14. CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend
  15. )
  16. from cryptography.hazmat.bindings.commoncrypto.binding import Binding
  17. from cryptography.hazmat.primitives.ciphers.algorithms import (
  18. AES, ARC4, Blowfish, CAST5, TripleDES
  19. )
  20. from cryptography.hazmat.primitives.ciphers.modes import (
  21. CBC, CFB, CFB8, CTR, ECB, GCM, OFB
  22. )
  23. HashMethods = namedtuple(
  24. "HashMethods", ["ctx", "hash_init", "hash_update", "hash_final"]
  25. )
  26. @utils.register_interface(CipherBackend)
  27. @utils.register_interface(HashBackend)
  28. @utils.register_interface(HMACBackend)
  29. @utils.register_interface(PBKDF2HMACBackend)
  30. class Backend(object):
  31. """
  32. CommonCrypto API wrapper.
  33. """
  34. name = "commoncrypto"
  35. def __init__(self):
  36. self._binding = Binding()
  37. self._ffi = self._binding.ffi
  38. self._lib = self._binding.lib
  39. self._cipher_registry = {}
  40. self._register_default_ciphers()
  41. self._hash_mapping = {
  42. "md5": HashMethods(
  43. "CC_MD5_CTX *", self._lib.CC_MD5_Init,
  44. self._lib.CC_MD5_Update, self._lib.CC_MD5_Final
  45. ),
  46. "sha1": HashMethods(
  47. "CC_SHA1_CTX *", self._lib.CC_SHA1_Init,
  48. self._lib.CC_SHA1_Update, self._lib.CC_SHA1_Final
  49. ),
  50. "sha224": HashMethods(
  51. "CC_SHA256_CTX *", self._lib.CC_SHA224_Init,
  52. self._lib.CC_SHA224_Update, self._lib.CC_SHA224_Final
  53. ),
  54. "sha256": HashMethods(
  55. "CC_SHA256_CTX *", self._lib.CC_SHA256_Init,
  56. self._lib.CC_SHA256_Update, self._lib.CC_SHA256_Final
  57. ),
  58. "sha384": HashMethods(
  59. "CC_SHA512_CTX *", self._lib.CC_SHA384_Init,
  60. self._lib.CC_SHA384_Update, self._lib.CC_SHA384_Final
  61. ),
  62. "sha512": HashMethods(
  63. "CC_SHA512_CTX *", self._lib.CC_SHA512_Init,
  64. self._lib.CC_SHA512_Update, self._lib.CC_SHA512_Final
  65. ),
  66. }
  67. self._supported_hmac_algorithms = {
  68. "md5": self._lib.kCCHmacAlgMD5,
  69. "sha1": self._lib.kCCHmacAlgSHA1,
  70. "sha224": self._lib.kCCHmacAlgSHA224,
  71. "sha256": self._lib.kCCHmacAlgSHA256,
  72. "sha384": self._lib.kCCHmacAlgSHA384,
  73. "sha512": self._lib.kCCHmacAlgSHA512,
  74. }
  75. self._supported_pbkdf2_hmac_algorithms = {
  76. "sha1": self._lib.kCCPRFHmacAlgSHA1,
  77. "sha224": self._lib.kCCPRFHmacAlgSHA224,
  78. "sha256": self._lib.kCCPRFHmacAlgSHA256,
  79. "sha384": self._lib.kCCPRFHmacAlgSHA384,
  80. "sha512": self._lib.kCCPRFHmacAlgSHA512,
  81. }
  82. def hash_supported(self, algorithm):
  83. return algorithm.name in self._hash_mapping
  84. def hmac_supported(self, algorithm):
  85. return algorithm.name in self._supported_hmac_algorithms
  86. def create_hash_ctx(self, algorithm):
  87. return _HashContext(self, algorithm)
  88. def create_hmac_ctx(self, key, algorithm):
  89. return _HMACContext(self, key, algorithm)
  90. def cipher_supported(self, cipher, mode):
  91. return (type(cipher), type(mode)) in self._cipher_registry
  92. def create_symmetric_encryption_ctx(self, cipher, mode):
  93. if isinstance(mode, GCM):
  94. return _GCMCipherContext(
  95. self, cipher, mode, self._lib.kCCEncrypt
  96. )
  97. else:
  98. return _CipherContext(self, cipher, mode, self._lib.kCCEncrypt)
  99. def create_symmetric_decryption_ctx(self, cipher, mode):
  100. if isinstance(mode, GCM):
  101. return _GCMCipherContext(
  102. self, cipher, mode, self._lib.kCCDecrypt
  103. )
  104. else:
  105. return _CipherContext(self, cipher, mode, self._lib.kCCDecrypt)
  106. def pbkdf2_hmac_supported(self, algorithm):
  107. return algorithm.name in self._supported_pbkdf2_hmac_algorithms
  108. def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
  109. key_material):
  110. alg_enum = self._supported_pbkdf2_hmac_algorithms[algorithm.name]
  111. buf = self._ffi.new("char[]", length)
  112. res = self._lib.CCKeyDerivationPBKDF(
  113. self._lib.kCCPBKDF2,
  114. key_material,
  115. len(key_material),
  116. salt,
  117. len(salt),
  118. alg_enum,
  119. iterations,
  120. buf,
  121. length
  122. )
  123. self._check_cipher_response(res)
  124. return self._ffi.buffer(buf)[:]
  125. def _register_cipher_adapter(self, cipher_cls, cipher_const, mode_cls,
  126. mode_const):
  127. if (cipher_cls, mode_cls) in self._cipher_registry:
  128. raise ValueError("Duplicate registration for: {0} {1}.".format(
  129. cipher_cls, mode_cls)
  130. )
  131. self._cipher_registry[cipher_cls, mode_cls] = (cipher_const,
  132. mode_const)
  133. def _register_default_ciphers(self):
  134. for mode_cls, mode_const in [
  135. (CBC, self._lib.kCCModeCBC),
  136. (ECB, self._lib.kCCModeECB),
  137. (CFB, self._lib.kCCModeCFB),
  138. (CFB8, self._lib.kCCModeCFB8),
  139. (OFB, self._lib.kCCModeOFB),
  140. (CTR, self._lib.kCCModeCTR),
  141. (GCM, self._lib.kCCModeGCM),
  142. ]:
  143. self._register_cipher_adapter(
  144. AES,
  145. self._lib.kCCAlgorithmAES128,
  146. mode_cls,
  147. mode_const
  148. )
  149. for mode_cls, mode_const in [
  150. (CBC, self._lib.kCCModeCBC),
  151. (ECB, self._lib.kCCModeECB),
  152. (CFB, self._lib.kCCModeCFB),
  153. (CFB8, self._lib.kCCModeCFB8),
  154. (OFB, self._lib.kCCModeOFB),
  155. ]:
  156. self._register_cipher_adapter(
  157. TripleDES,
  158. self._lib.kCCAlgorithm3DES,
  159. mode_cls,
  160. mode_const
  161. )
  162. for mode_cls, mode_const in [
  163. (CBC, self._lib.kCCModeCBC),
  164. (ECB, self._lib.kCCModeECB),
  165. (CFB, self._lib.kCCModeCFB),
  166. (OFB, self._lib.kCCModeOFB)
  167. ]:
  168. self._register_cipher_adapter(
  169. Blowfish,
  170. self._lib.kCCAlgorithmBlowfish,
  171. mode_cls,
  172. mode_const
  173. )
  174. for mode_cls, mode_const in [
  175. (CBC, self._lib.kCCModeCBC),
  176. (ECB, self._lib.kCCModeECB),
  177. (CFB, self._lib.kCCModeCFB),
  178. (OFB, self._lib.kCCModeOFB),
  179. (CTR, self._lib.kCCModeCTR)
  180. ]:
  181. self._register_cipher_adapter(
  182. CAST5,
  183. self._lib.kCCAlgorithmCAST,
  184. mode_cls,
  185. mode_const
  186. )
  187. self._register_cipher_adapter(
  188. ARC4,
  189. self._lib.kCCAlgorithmRC4,
  190. type(None),
  191. self._lib.kCCModeRC4
  192. )
  193. def _check_cipher_response(self, response):
  194. if response == self._lib.kCCSuccess:
  195. return
  196. elif response == self._lib.kCCAlignmentError:
  197. # This error is not currently triggered due to a bug filed as
  198. # rdar://15589470
  199. raise ValueError(
  200. "The length of the provided data is not a multiple of "
  201. "the block length."
  202. )
  203. else:
  204. raise InternalError(
  205. "The backend returned an unknown error, consider filing a bug."
  206. " Code: {0}.".format(response)
  207. )
  208. def _release_cipher_ctx(self, ctx):
  209. """
  210. Called by the garbage collector and used to safely dereference and
  211. release the context.
  212. """
  213. if ctx[0] != self._ffi.NULL:
  214. res = self._lib.CCCryptorRelease(ctx[0])
  215. self._check_cipher_response(res)
  216. ctx[0] = self._ffi.NULL
  217. backend = Backend()