1#
2# A block cipher is instantiated as a combination of:
3# 1. A base cipher (such as AES)
4# 2. A mode of operation (such as CBC)
5#
6# Both items are implemented as C modules.
7#
8# The API of #1 is (replace "AES" with the name of the actual cipher):
9# - AES_start_operaion(key) --> base_cipher_state
10# - AES_encrypt(base_cipher_state, in, out, length)
11# - AES_decrypt(base_cipher_state, in, out, length)
12# - AES_stop_operation(base_cipher_state)
13#
14# Where base_cipher_state is AES_State, a struct with BlockBase (set of
15# pointers to encrypt/decrypt/stop) followed by cipher-specific data.
16#
17# The API of #2 is (replace "CBC" with the name of the actual mode):
18# - CBC_start_operation(base_cipher_state) --> mode_state
19# - CBC_encrypt(mode_state, in, out, length)
20# - CBC_decrypt(mode_state, in, out, length)
21# - CBC_stop_operation(mode_state)
22#
23# where mode_state is a a pointer to base_cipher_state plus mode-specific data.
24
25from __future__ import annotations
26
27from typing import TYPE_CHECKING, TypedDict, Union
28
29if TYPE_CHECKING:
30 from Crypto.Util.Counter import CounterParams
31
32Buffer = Union[bytes, bytearray, memoryview]
33
34
35class BlockCipherParams(TypedDict, total=False):
36 """Optional keyword arguments of ``new()`` for the classic block ciphers.
37 Which ones are accepted depends on the mode of operation."""
38
39 iv: Buffer
40 IV: Buffer
41 nonce: Buffer
42 segment_size: int
43 mac_len: int
44 msg_len: int
45 assoc_len: int
46 initial_value: Union[int, Buffer]
47 counter: CounterParams
48 threads: int
49
50
51def _create_cipher(factory, key, mode, *args, **kwargs):
52 kwargs["key"] = key
53
54 if args:
55 if mode in (8, 9, 10, 11, 12):
56 if len(args) > 1:
57 raise TypeError("Too many arguments for this mode")
58 kwargs["nonce"] = args[0]
59 elif mode in (2, 3, 5, 7):
60 if len(args) > 1:
61 raise TypeError("Too many arguments for this mode")
62 kwargs["IV"] = args[0]
63 elif mode == 6:
64 if len(args) > 0:
65 raise TypeError("Too many arguments for this mode")
66 elif mode == 1:
67 raise TypeError("IV is not meaningful for the ECB mode")
68
69 res = None
70 extra_modes = kwargs.pop("add_aes_modes", False)
71
72 if mode == 1:
73 from Crypto.Cipher._mode_ecb import _create_ecb_cipher
74
75 res = _create_ecb_cipher(factory, **kwargs)
76 elif mode == 2:
77 from Crypto.Cipher._mode_cbc import _create_cbc_cipher
78
79 res = _create_cbc_cipher(factory, **kwargs)
80 elif mode == 3:
81 from Crypto.Cipher._mode_cfb import _create_cfb_cipher
82
83 res = _create_cfb_cipher(factory, **kwargs)
84 elif mode == 5:
85 from Crypto.Cipher._mode_ofb import _create_ofb_cipher
86
87 res = _create_ofb_cipher(factory, **kwargs)
88 elif mode == 6:
89 from Crypto.Cipher._mode_ctr import _create_ctr_cipher
90
91 res = _create_ctr_cipher(factory, **kwargs)
92 elif mode == 7:
93 from Crypto.Cipher._mode_openpgp import _create_openpgp_cipher
94
95 res = _create_openpgp_cipher(factory, **kwargs)
96 elif mode == 9:
97 from Crypto.Cipher._mode_eax import _create_eax_cipher
98
99 res = _create_eax_cipher(factory, **kwargs)
100 elif extra_modes:
101 if mode == 8:
102 from Crypto.Cipher._mode_ccm import _create_ccm_cipher
103
104 res = _create_ccm_cipher(factory, **kwargs)
105 elif mode == 10:
106 from Crypto.Cipher._mode_siv import _create_siv_cipher
107
108 res = _create_siv_cipher(factory, **kwargs)
109 elif mode == 11:
110 from Crypto.Cipher._mode_gcm import _create_gcm_cipher
111
112 res = _create_gcm_cipher(factory, **kwargs)
113 elif mode == 12:
114 from Crypto.Cipher._mode_ocb import _create_ocb_cipher
115
116 res = _create_ocb_cipher(factory, **kwargs)
117 elif mode == 13:
118 from Crypto.Cipher._mode_kw import _create_kw_cipher
119
120 res = _create_kw_cipher(factory, **kwargs)
121 elif mode == 14:
122 from Crypto.Cipher._mode_kwp import _create_kwp_cipher
123
124 res = _create_kwp_cipher(factory, **kwargs)
125
126 if res is None:
127 raise ValueError("Mode not supported")
128
129 return res