File: defs.py

package info (click to toggle)
python-yubihsm 3.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 452 kB
  • sloc: python: 4,882; makefile: 4
file content (473 lines) | stat: -rw-r--r-- 11,769 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
# Copyright 2016-2018 Yubico AB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Named constants used in YubiHSM commands."""

from enum import IntEnum, IntFlag, unique
from typing import Tuple

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec

Version = Tuple[int, int, int]


@unique
class ERROR(IntEnum):
    """Error codes returned by the YubiHSM"""

    OK = 0x00
    INVALID_COMMAND = 0x01
    INVALID_DATA = 0x02
    INVALID_SESSION = 0x03
    AUTHENTICATION_FAILED = 0x04
    SESSIONS_FULL = 0x05
    SESSION_FAILED = 0x06
    STORAGE_FAILED = 0x07
    WRONG_LENGTH = 0x08
    INSUFFICIENT_PERMISSIONS = 0x09
    LOG_FULL = 0x0A
    OBJECT_NOT_FOUND = 0x0B
    INVALID_ID = 0x0C
    SSH_CA_CONSTRAINT_VIOLATION = 0x0E
    INVALID_OTP = 0x0F
    DEMO_MODE = 0x10
    OBJECT_EXISTS = 0x11
    ALGORITHM_DISABLED = 0x12
    COMMAND_UNEXECUTED = 0xFF

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)


@unique
class COMMAND(IntEnum):
    """Commands available to send to the YubiHSM"""

    ECHO = 0x01
    CREATE_SESSION = 0x03
    AUTHENTICATE_SESSION = 0x04
    SESSION_MESSAGE = 0x05
    DEVICE_INFO = 0x06
    RESET_DEVICE = 0x08
    GET_DEVICE_PUBLIC_KEY = 0x0A
    CLOSE_SESSION = 0x40
    GET_STORAGE_INFO = 0x041
    PUT_OPAQUE = 0x42
    GET_OPAQUE = 0x43
    PUT_AUTHENTICATION_KEY = 0x44
    PUT_ASYMMETRIC_KEY = 0x45
    GENERATE_ASYMMETRIC_KEY = 0x46
    SIGN_PKCS1 = 0x47
    LIST_OBJECTS = 0x48
    DECRYPT_PKCS1 = 0x49
    EXPORT_WRAPPED = 0x4A
    IMPORT_WRAPPED = 0x4B
    PUT_WRAP_KEY = 0x4C
    GET_LOG_ENTRIES = 0x4D
    GET_OBJECT_INFO = 0x4E
    SET_OPTION = 0x4F
    GET_OPTION = 0x50
    GET_PSEUDO_RANDOM = 0x51
    PUT_HMAC_KEY = 0x52
    SIGN_HMAC = 0x53
    GET_PUBLIC_KEY = 0x54
    SIGN_PSS = 0x55
    SIGN_ECDSA = 0x56
    DERIVE_ECDH = 0x57
    DELETE_OBJECT = 0x58
    DECRYPT_OAEP = 0x59
    GENERATE_HMAC_KEY = 0x5A
    GENERATE_WRAP_KEY = 0x5B
    VERIFY_HMAC = 0x5C
    SIGN_SSH_CERTIFICATE = 0x5D
    PUT_TEMPLATE = 0x5E
    GET_TEMPLATE = 0x5F
    DECRYPT_OTP = 0x60
    CREATE_OTP_AEAD = 0x61
    RANDOMIZE_OTP_AEAD = 0x62
    REWRAP_OTP_AEAD = 0x63
    SIGN_ATTESTATION_CERTIFICATE = 0x64
    PUT_OTP_AEAD_KEY = 0x65
    GENERATE_OTP_AEAD_KEY = 0x66
    SET_LOG_INDEX = 0x67
    WRAP_DATA = 0x68
    UNWRAP_DATA = 0x69
    SIGN_EDDSA = 0x6A
    BLINK_DEVICE = 0x6B
    CHANGE_AUTHENTICATION_KEY = 0x6C
    PUT_SYMMETRIC_KEY = 0x6D
    GENERATE_SYMMETRIC_KEY = 0x6E
    DECRYPT_ECB = 0x6F
    ENCRYPT_ECB = 0x70
    DECRYPT_CBC = 0x71
    ENCRYPT_CBC = 0x72
    PUT_PUBLIC_WRAP_KEY = 0x73
    WRAP_KEY_RSA = 0x74
    UNWRAP_KEY_RSA = 0x75
    EXPORT_WRAPPED_RSA = 0x76
    IMPORT_WRAPPED_RSA = 0x77

    ERROR = 0x7F

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)


@unique
class ALGORITHM(IntEnum):
    """Various algorithm constants"""

    RSA_PKCS1_SHA1 = 1
    RSA_PKCS1_SHA256 = 2
    RSA_PKCS1_SHA384 = 3
    RSA_PKCS1_SHA512 = 4
    RSA_PSS_SHA1 = 5
    RSA_PSS_SHA256 = 6
    RSA_PSS_SHA384 = 7
    RSA_PSS_SHA512 = 8
    RSA_2048 = 9
    RSA_3072 = 10
    RSA_4096 = 11
    RSA_OAEP_SHA1 = 25
    RSA_OAEP_SHA256 = 26
    RSA_OAEP_SHA384 = 27
    RSA_OAEP_SHA512 = 28
    RSA_MGF1_SHA1 = 32
    RSA_MGF1_SHA256 = 33
    RSA_MGF1_SHA384 = 34
    RSA_MGF1_SHA512 = 35

    EC_P256 = 12
    EC_P384 = 13
    EC_P521 = 14
    EC_K256 = 15
    EC_BP256 = 16
    EC_BP384 = 17
    EC_BP512 = 18

    EC_ECDSA_SHA1 = 23
    EC_ECDH = 24

    HMAC_SHA1 = 19
    HMAC_SHA256 = 20
    HMAC_SHA384 = 21
    HMAC_SHA512 = 22

    AES128_CCM_WRAP = 29
    OPAQUE_DATA = 30
    OPAQUE_X509_CERTIFICATE = 31
    TEMPLATE_SSH = 36
    AES128_YUBICO_OTP = 37
    AES128_YUBICO_AUTHENTICATION = 38
    AES192_YUBICO_OTP = 39
    AES256_YUBICO_OTP = 40
    AES192_CCM_WRAP = 41
    AES256_CCM_WRAP = 42
    EC_ECDSA_SHA256 = 43
    EC_ECDSA_SHA384 = 44
    EC_ECDSA_SHA512 = 45
    EC_ED25519 = 46
    EC_P224 = 47
    RSA_PKCS1_DECRYPT = 48
    EC_P256_YUBICO_AUTHENTICATION = 49

    AES128 = 50
    AES192 = 51
    AES256 = 52
    AES_ECB = 53
    AES_CBC = 54
    AES_KWP = 55

    def __str__(self):
        return repr(self)

    def to_curve(self) -> ec.EllipticCurve:
        """Return a Cryptography EC curve instance for a given member.

        :return: The corresponding curve.
        :rtype: cryptography.hazmat.primitives.ec.

        :Example:

        >>> isinstance(ALGORITHM.EC_P256.to_curve(), ec.SECP256R1)
        True
        """

        return _curve_table[self]()  # type: ignore

    @staticmethod
    def for_curve(curve: ec.EllipticCurve) -> "ALGORITHM":
        """Returns a member corresponding to a Cryptography curve instance.

        :Example:

        >>> ALGORITHM.for_curve(ec.SECP256R1()) == ALGORITHM.EC_P256
        True
        """

        curve_type = type(curve)
        for key, val in _curve_table.items():
            if val == curve_type:
                return key
        raise ValueError("Unsupported curve type: %s" % curve.name)

    def to_key_size(self) -> int:
        """Return the expected size (in bytes) of a key corresponding to an algorithm.

        :return: The corresponding key size (in bytes) to an algorithm.

        :Example:

        >>> ALGORITHM.AES128.to_key_size()
        16
        """

        return _key_size_table[self]

    def to_hash_algorithm(self) -> hashes.HashAlgorithm:
        """Return the cryptography hash algorithm object corresponding to the algorithm.

        :return The corresponding cryptography hash algorithm object.

        :Example:

        >>> ALGORITHM.HMAC_SHA1.to_hash_algorithm()
        hashes.SHA1
        """

        return _hash_table[self]()


_curve_table = {
    ALGORITHM.EC_P224: ec.SECP224R1,
    ALGORITHM.EC_P256: ec.SECP256R1,
    ALGORITHM.EC_P384: ec.SECP384R1,
    ALGORITHM.EC_P521: ec.SECP521R1,
    ALGORITHM.EC_K256: ec.SECP256K1,
    ALGORITHM.EC_BP256: ec.BrainpoolP256R1,
    ALGORITHM.EC_BP384: ec.BrainpoolP384R1,
    ALGORITHM.EC_BP512: ec.BrainpoolP512R1,
}

_key_size_table = {
    ALGORITHM.AES128_CCM_WRAP: 16,
    ALGORITHM.AES192_CCM_WRAP: 24,
    ALGORITHM.AES256_CCM_WRAP: 32,
    ALGORITHM.HMAC_SHA1: 64,  # Maximum key size
    ALGORITHM.HMAC_SHA256: 64,  # Maximum key size
    ALGORITHM.HMAC_SHA384: 128,  # Maximum key size
    ALGORITHM.HMAC_SHA512: 128,  # Maximum key size
    ALGORITHM.AES128_YUBICO_OTP: 16,
    ALGORITHM.AES192_YUBICO_OTP: 24,
    ALGORITHM.AES256_YUBICO_OTP: 32,
    ALGORITHM.AES128: 16,
    ALGORITHM.AES192: 24,
    ALGORITHM.AES256: 32,
    ALGORITHM.RSA_2048: 256,
    ALGORITHM.RSA_3072: 384,
    ALGORITHM.RSA_4096: 512,
}

_hash_table = {
    ALGORITHM.HMAC_SHA1: hashes.SHA1,
    ALGORITHM.HMAC_SHA256: hashes.SHA256,
    ALGORITHM.HMAC_SHA384: hashes.SHA384,
    ALGORITHM.HMAC_SHA512: hashes.SHA512,
}


@unique
class LIST_FILTER(IntEnum):
    """Keys for use to filter on in list_objects"""

    ID = 0x01
    TYPE = 0x02
    DOMAINS = 0x03
    CAPABILITIES = 0x04
    ALGORITHM = 0x05
    LABEL = 0x06

    def __str__(self):
        return repr(self)


@unique
class OBJECT(IntEnum):
    """YubiHSM object types"""

    OPAQUE = 0x01
    AUTHENTICATION_KEY = 0x02
    ASYMMETRIC_KEY = 0x03
    WRAP_KEY = 0x04
    HMAC_KEY = 0x05
    TEMPLATE = 0x06
    OTP_AEAD_KEY = 0x07
    SYMMETRIC_KEY = 0x08
    PUBLIC_WRAP_KEY = 0x09

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)


@unique
class OPTION(IntEnum):
    """YubiHSM device options"""

    FORCE_AUDIT = 0x01
    COMMAND_AUDIT = 0x03
    ALGORITHM_TOGGLE = 0x04
    FIPS_MODE = 0x05

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)


@unique
class AUDIT(IntEnum):
    """Values for audit options"""

    OFF = 0x00
    ON = 0x01
    FIXED = 0x02

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)


@unique
class FIPS_STATUS(IntEnum):
    """Values for FIPS status"""

    OFF = 0x00
    ON = 0x01
    PENDING = 0x03

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)


class _enum_prop:
    # Static property for use with enums.
    def __init__(self, getter):
        self.getter = getter

    def __get__(self, instance, cls):
        return self.getter(cls)


@unique
class CAPABILITY(IntFlag):
    """YubiHSM object capability flags"""

    GET_OPAQUE = 1 << 0x00
    PUT_OPAQUE = 1 << 0x01
    PUT_AUTHENTICATION_KEY = 1 << 0x02
    PUT_ASYMMETRIC = 1 << 0x03
    GENERATE_ASYMMETRIC_KEY = 1 << 0x04
    SIGN_PKCS = 1 << 0x05
    SIGN_PSS = 1 << 0x06
    SIGN_ECDSA = 1 << 0x07
    SIGN_EDDSA = 1 << 0x08
    DECRYPT_PKCS = 1 << 0x09
    DECRYPT_OAEP = 1 << 0x0A
    DERIVE_ECDH = 1 << 0x0B
    EXPORT_WRAPPED = 1 << 0x0C
    IMPORT_WRAPPED = 1 << 0x0D
    PUT_WRAP_KEY = 1 << 0x0E
    GENERATE_WRAP_KEY = 1 << 0x0F
    EXPORTABLE_UNDER_WRAP = 1 << 0x10
    SET_OPTION = 1 << 0x11
    GET_OPTION = 1 << 0x12
    GET_PSEUDO_RANDOM = 1 << 0x13
    PUT_HMAC_KEY = 1 << 0x14
    GENERATE_HMAC_KEY = 1 << 0x15
    SIGN_HMAC = 1 << 0x16
    VERIFY_HMAC = 1 << 0x17
    GET_LOG_ENTRIES = 1 << 0x18
    SIGN_SSH_CERTIFICATE = 1 << 0x19
    GET_TEMPLATE = 1 << 0x1A
    PUT_TEMPLATE = 1 << 0x1B
    RESET_DEVICE = 1 << 0x1C
    DECRYPT_OTP = 1 << 0x1D
    CREATE_OTP_AEAD = 1 << 0x1E
    RANDOMIZE_OTP_AEAD = 1 << 0x1F
    REWRAP_FROM_OTP_AEAD_KEY = 1 << 0x20
    REWRAP_TO_OTP_AEAD_KEY = 1 << 0x21
    SIGN_ATTESTATION_CERTIFICATE = 1 << 0x22
    PUT_OTP_AEAD_KEY = 1 << 0x23
    GENERATE_OTP_AEAD_KEY = 1 << 0x24
    WRAP_DATA = 1 << 0x25
    UNWRAP_DATA = 1 << 0x26
    DELETE_OPAQUE = 1 << 0x27
    DELETE_AUTHENTICATION_KEY = 1 << 0x28
    DELETE_ASYMMETRIC_KEY = 1 << 0x29
    DELETE_WRAP_KEY = 1 << 0x2A
    DELETE_HMAC_KEY = 1 << 0x2B
    DELETE_TEMPLATE = 1 << 0x2C
    DELETE_OTP_AEAD_KEY = 1 << 0x2D
    CHANGE_AUTHENTICATION_KEY = 1 << 0x2E
    PUT_SYMMETRIC_KEY = 1 << 0x2F
    GENERATE_SYMMETRIC_KEY = 1 << 0x30
    DELETE_SYMMETRIC_KEY = 1 << 0x31
    DECRYPT_ECB = 1 << 0x32
    ENCRYPT_ECB = 1 << 0x33
    DECRYPT_CBC = 1 << 0x34
    ENCRYPT_CBC = 1 << 0x35
    PUBLIC_WRAP_KEY_WRITE = 1 << 0x36
    PUBLIC_WRAP_KEY_DELETE = 1 << 0x37

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)

    @_enum_prop
    def NONE(cls) -> "CAPABILITY":
        return cls(0)  # type: ignore

    @_enum_prop
    def ALL(cls) -> "CAPABILITY":
        return cls(sum(cls))  # type: ignore


class ORIGIN(IntFlag):
    GENERATED = 0x01
    IMPORTED = 0x02
    IMPORTED_WRAPPED = 0x10  # Set in combination with GENERATED/IMPORTED

    def __repr__(self):
        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, hex(self))

    def __str__(self):
        return repr(self)