python-pkcs11 0.10.1__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pkcs11/attributes.py ADDED
@@ -0,0 +1,272 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+ from datetime import datetime
5
+ from enum import IntEnum
6
+ from struct import Struct
7
+ from typing import Any, Final
8
+
9
+ from pkcs11.constants import Attribute, CertificateType, MechanismFlag, ObjectClass
10
+ from pkcs11.mechanisms import KeyType, Mechanism
11
+
12
+ # Type aliases for pack/unpack function pairs
13
+ PackFunc = Callable[[Any], bytes]
14
+ UnpackFunc = Callable[[bytes], Any]
15
+ Handler = tuple[PackFunc, UnpackFunc]
16
+
17
+ # (Pack Function, Unpack Function) functions
18
+ _bool_struct = Struct("?")
19
+ _ulong_struct = Struct("L")
20
+
21
+ handle_bool: Handler = (
22
+ _bool_struct.pack,
23
+ lambda v: False if len(v) == 0 else _bool_struct.unpack(v)[0],
24
+ )
25
+ handle_ulong: Handler = (_ulong_struct.pack, lambda v: _ulong_struct.unpack(v)[0])
26
+ handle_str: Handler = (lambda s: s.encode("utf-8"), lambda b: b.decode("utf-8"))
27
+ handle_date: Handler = (
28
+ lambda s: s.strftime("%Y%m%d").encode("ascii"),
29
+ lambda s: datetime.strptime(s.decode("ascii"), "%Y%m%d").date(), # noqa: DTZ007
30
+ )
31
+ handle_bytes: Handler = (bytes, bytes)
32
+ # The PKCS#11 biginteger type is an array of bytes in network byte order.
33
+ # If you have an int type, wrap it in biginteger()
34
+ handle_biginteger: Handler = handle_bytes
35
+
36
+
37
+ def _enum(type_: type[IntEnum]) -> Handler:
38
+ """Factory to pack/unpack ints into IntEnums."""
39
+ pack, unpack = handle_ulong
40
+
41
+ return (lambda v: pack(int(v)), lambda v: type_(unpack(v)))
42
+
43
+
44
+ ATTRIBUTE_TYPES: dict[Attribute, Handler] = {
45
+ Attribute.ALWAYS_AUTHENTICATE: handle_bool,
46
+ Attribute.ALWAYS_SENSITIVE: handle_bool,
47
+ Attribute.APPLICATION: handle_str,
48
+ Attribute.BASE: handle_biginteger,
49
+ Attribute.CERTIFICATE_TYPE: _enum(CertificateType),
50
+ Attribute.CHECK_VALUE: handle_bytes,
51
+ Attribute.CLASS: _enum(ObjectClass),
52
+ Attribute.COEFFICIENT: handle_biginteger,
53
+ Attribute.DECAPSULATE: handle_bool,
54
+ Attribute.DECRYPT: handle_bool,
55
+ Attribute.DERIVE: handle_bool,
56
+ Attribute.EC_PARAMS: handle_bytes,
57
+ Attribute.EC_POINT: handle_bytes,
58
+ Attribute.ENCAPSULATE: handle_bool,
59
+ Attribute.ENCRYPT: handle_bool,
60
+ Attribute.END_DATE: handle_date,
61
+ Attribute.EXPONENT_1: handle_biginteger,
62
+ Attribute.EXPONENT_2: handle_biginteger,
63
+ Attribute.EXTRACTABLE: handle_bool,
64
+ Attribute.HASH_OF_ISSUER_PUBLIC_KEY: handle_bytes,
65
+ Attribute.HASH_OF_SUBJECT_PUBLIC_KEY: handle_bytes,
66
+ Attribute.ID: handle_bytes,
67
+ Attribute.ISSUER: handle_bytes,
68
+ Attribute.KEY_GEN_MECHANISM: _enum(Mechanism),
69
+ Attribute.KEY_TYPE: _enum(KeyType),
70
+ Attribute.LABEL: handle_str,
71
+ Attribute.LOCAL: handle_bool,
72
+ Attribute.MODIFIABLE: handle_bool,
73
+ Attribute.COPYABLE: handle_bool,
74
+ Attribute.DESTROYABLE: handle_bool,
75
+ Attribute.MODULUS: handle_biginteger,
76
+ Attribute.MODULUS_BITS: handle_ulong,
77
+ Attribute.NEVER_EXTRACTABLE: handle_bool,
78
+ Attribute.OBJECT_ID: handle_bytes,
79
+ Attribute.PARAMETER_SET: handle_ulong,
80
+ Attribute.PRIME: handle_biginteger,
81
+ Attribute.PRIME_BITS: handle_ulong,
82
+ Attribute.PRIME_1: handle_biginteger,
83
+ Attribute.PRIME_2: handle_biginteger,
84
+ Attribute.PRIVATE: handle_bool,
85
+ Attribute.PRIVATE_EXPONENT: handle_biginteger,
86
+ Attribute.PUBLIC_EXPONENT: handle_biginteger,
87
+ Attribute.SENSITIVE: handle_bool,
88
+ Attribute.SEED: handle_bytes,
89
+ Attribute.SERIAL_NUMBER: handle_bytes,
90
+ Attribute.SIGN: handle_bool,
91
+ Attribute.SIGN_RECOVER: handle_bool,
92
+ Attribute.START_DATE: handle_date,
93
+ Attribute.SUBJECT: handle_bytes,
94
+ Attribute.SUBPRIME: handle_biginteger,
95
+ Attribute.SUBPRIME_BITS: handle_ulong,
96
+ Attribute.TOKEN: handle_bool,
97
+ Attribute.TRUSTED: handle_bool,
98
+ Attribute.UNIQUE_ID: handle_str,
99
+ Attribute.UNWRAP: handle_bool,
100
+ Attribute.URL: handle_str,
101
+ Attribute.VALUE: handle_biginteger,
102
+ Attribute.VALUE_BITS: handle_ulong,
103
+ Attribute.VALUE_LEN: handle_ulong,
104
+ Attribute.VERIFY: handle_bool,
105
+ Attribute.VERIFY_RECOVER: handle_bool,
106
+ Attribute.WRAP: handle_bool,
107
+ Attribute.WRAP_WITH_TRUSTED: handle_bool,
108
+ Attribute.GOSTR3410_PARAMS: handle_bytes,
109
+ Attribute.GOSTR3411_PARAMS: handle_bytes,
110
+ }
111
+ """
112
+ Map of attributes to (serialize, deserialize) functions.
113
+ """
114
+
115
+ ALL_CAPABILITIES: Final[tuple[Attribute, ...]] = (
116
+ Attribute.ENCRYPT,
117
+ Attribute.DECRYPT,
118
+ Attribute.WRAP,
119
+ Attribute.UNWRAP,
120
+ Attribute.SIGN,
121
+ Attribute.VERIFY,
122
+ Attribute.DERIVE,
123
+ )
124
+
125
+
126
+ def _apply_common(
127
+ template: dict[Attribute, Any],
128
+ id_: bytes | None,
129
+ label: str | None,
130
+ store: bool,
131
+ ) -> None:
132
+ if id_:
133
+ template[Attribute.ID] = id_
134
+ if label:
135
+ template[Attribute.LABEL] = label
136
+ template[Attribute.TOKEN] = bool(store)
137
+
138
+
139
+ def _apply_capabilities(
140
+ template: dict[Attribute, Any],
141
+ possible_capas: tuple[Attribute, ...],
142
+ capabilities: MechanismFlag | int,
143
+ ) -> None:
144
+ for attr in possible_capas:
145
+ template[attr] = _capa_attr_to_mechanism_flag[attr] & capabilities
146
+
147
+
148
+ _capa_attr_to_mechanism_flag: Final[dict[Attribute, MechanismFlag]] = {
149
+ Attribute.ENCRYPT: MechanismFlag.ENCRYPT,
150
+ Attribute.DECRYPT: MechanismFlag.DECRYPT,
151
+ Attribute.WRAP: MechanismFlag.WRAP,
152
+ Attribute.UNWRAP: MechanismFlag.UNWRAP,
153
+ Attribute.SIGN: MechanismFlag.SIGN,
154
+ Attribute.VERIFY: MechanismFlag.VERIFY,
155
+ Attribute.DERIVE: MechanismFlag.DERIVE,
156
+ }
157
+
158
+
159
+ class AttributeMapper:
160
+ """
161
+ Class mapping PKCS#11 attributes to and from Python values.
162
+ """
163
+
164
+ attribute_types: dict[Attribute, Handler]
165
+ default_secret_key_template: dict[Attribute, Any]
166
+ default_public_key_template: dict[Attribute, Any]
167
+ default_private_key_template: dict[Attribute, Any]
168
+
169
+ def __init__(self) -> None:
170
+ self.attribute_types = dict(ATTRIBUTE_TYPES)
171
+ self.default_secret_key_template = {
172
+ Attribute.CLASS: ObjectClass.SECRET_KEY,
173
+ Attribute.ID: b"",
174
+ Attribute.LABEL: "",
175
+ Attribute.PRIVATE: True,
176
+ Attribute.SENSITIVE: True,
177
+ }
178
+ self.default_public_key_template = {
179
+ Attribute.CLASS: ObjectClass.PUBLIC_KEY,
180
+ Attribute.ID: b"",
181
+ Attribute.LABEL: "",
182
+ }
183
+ self.default_private_key_template = {
184
+ Attribute.CLASS: ObjectClass.PRIVATE_KEY,
185
+ Attribute.ID: b"",
186
+ Attribute.LABEL: "",
187
+ Attribute.PRIVATE: True,
188
+ Attribute.SENSITIVE: True,
189
+ }
190
+
191
+ def register_handler(self, key: Attribute, pack: PackFunc, unpack: UnpackFunc) -> None:
192
+ self.attribute_types[key] = (pack, unpack)
193
+
194
+ def _handler(self, key: Attribute) -> Handler:
195
+ try:
196
+ return self.attribute_types[key]
197
+ except KeyError as e:
198
+ raise NotImplementedError(f"Can't handle attribute type {hex(key)}.") from e
199
+
200
+ def pack_attribute(self, key: Attribute, value: Any) -> bytes:
201
+ """Pack a Attribute value into a bytes array."""
202
+ pack, _ = self._handler(key)
203
+ return pack(value)
204
+
205
+ def unpack_attributes(self, key: Attribute, value: bytes) -> Any:
206
+ """Unpack a Attribute bytes array into a Python value."""
207
+ _, unpack = self._handler(key)
208
+ return unpack(value)
209
+
210
+ def public_key_template(
211
+ self,
212
+ *,
213
+ capabilities: MechanismFlag | int,
214
+ id_: bytes | None,
215
+ label: str | None,
216
+ store: bool,
217
+ ) -> dict[Attribute, Any]:
218
+ template = dict(self.default_public_key_template)
219
+ _apply_capabilities(
220
+ template,
221
+ (Attribute.ENCRYPT, Attribute.WRAP, Attribute.VERIFY),
222
+ capabilities,
223
+ )
224
+ _apply_common(template, id_, label, store)
225
+ return template
226
+
227
+ def private_key_template(
228
+ self,
229
+ *,
230
+ capabilities: MechanismFlag | int,
231
+ id_: bytes | None,
232
+ label: str | None,
233
+ store: bool,
234
+ ) -> dict[Attribute, Any]:
235
+ template = dict(self.default_private_key_template)
236
+ _apply_capabilities(
237
+ template,
238
+ (Attribute.DECRYPT, Attribute.UNWRAP, Attribute.SIGN, Attribute.DERIVE),
239
+ capabilities,
240
+ )
241
+ _apply_common(template, id_, label, store)
242
+ return template
243
+
244
+ def secret_key_template(
245
+ self,
246
+ *,
247
+ capabilities: MechanismFlag | int,
248
+ id_: bytes | None,
249
+ label: str | None,
250
+ store: bool,
251
+ ) -> dict[Attribute, Any]:
252
+ return self.generic_key_template(
253
+ self.default_secret_key_template,
254
+ capabilities=capabilities,
255
+ id_=id_,
256
+ label=label,
257
+ store=store,
258
+ )
259
+
260
+ def generic_key_template(
261
+ self,
262
+ base_template: dict[Attribute, Any],
263
+ *,
264
+ capabilities: MechanismFlag | int,
265
+ id_: bytes | None,
266
+ label: str | None,
267
+ store: bool,
268
+ ) -> dict[Attribute, Any]:
269
+ template = dict(base_template)
270
+ _apply_capabilities(template, ALL_CAPABILITIES, capabilities)
271
+ _apply_common(template, id_, label, store)
272
+ return template