• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5from __future__ import absolute_import, division, print_function
6
7from cryptography import utils
8from cryptography.hazmat.backends.openssl.utils import _evp_pkey_derive
9from cryptography.hazmat.primitives import serialization
10from cryptography.hazmat.primitives.asymmetric.x448 import (
11    X448PrivateKey, X448PublicKey
12)
13
14_X448_KEY_SIZE = 56
15
16
17@utils.register_interface(X448PublicKey)
18class _X448PublicKey(object):
19    def __init__(self, backend, evp_pkey):
20        self._backend = backend
21        self._evp_pkey = evp_pkey
22
23    def public_bytes(self, encoding, format):
24        if (
25            encoding is serialization.Encoding.Raw or
26            format is serialization.PublicFormat.Raw
27        ):
28            if (
29                encoding is not serialization.Encoding.Raw or
30                format is not serialization.PublicFormat.Raw
31            ):
32                raise ValueError(
33                    "When using Raw both encoding and format must be Raw"
34                )
35
36            return self._raw_public_bytes()
37
38        if (
39            encoding in serialization._PEM_DER and
40            format is not serialization.PublicFormat.SubjectPublicKeyInfo
41        ):
42            raise ValueError(
43                "format must be SubjectPublicKeyInfo when encoding is PEM or "
44                "DER"
45            )
46
47        return self._backend._public_key_bytes(
48            encoding, format, self, self._evp_pkey, None
49        )
50
51    def _raw_public_bytes(self):
52        buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE)
53        buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE)
54        res = self._backend._lib.EVP_PKEY_get_raw_public_key(
55            self._evp_pkey, buf, buflen
56        )
57        self._backend.openssl_assert(res == 1)
58        self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE)
59        return self._backend._ffi.buffer(buf, _X448_KEY_SIZE)[:]
60
61
62@utils.register_interface(X448PrivateKey)
63class _X448PrivateKey(object):
64    def __init__(self, backend, evp_pkey):
65        self._backend = backend
66        self._evp_pkey = evp_pkey
67
68    def public_key(self):
69        buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE)
70        buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE)
71        res = self._backend._lib.EVP_PKEY_get_raw_public_key(
72            self._evp_pkey, buf, buflen
73        )
74        self._backend.openssl_assert(res == 1)
75        self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE)
76        return self._backend.x448_load_public_bytes(buf)
77
78    def exchange(self, peer_public_key):
79        if not isinstance(peer_public_key, X448PublicKey):
80            raise TypeError("peer_public_key must be X448PublicKey.")
81
82        return _evp_pkey_derive(
83            self._backend, self._evp_pkey, peer_public_key
84        )
85
86    def private_bytes(self, encoding, format, encryption_algorithm):
87        if (
88            encoding is serialization.Encoding.Raw or
89            format is serialization.PublicFormat.Raw
90        ):
91            if (
92                format is not serialization.PrivateFormat.Raw or
93                encoding is not serialization.Encoding.Raw or not
94                isinstance(encryption_algorithm, serialization.NoEncryption)
95            ):
96                raise ValueError(
97                    "When using Raw both encoding and format must be Raw "
98                    "and encryption_algorithm must be NoEncryption"
99                )
100
101            return self._raw_private_bytes()
102
103        if (
104            encoding in serialization._PEM_DER and
105            format is not serialization.PrivateFormat.PKCS8
106        ):
107            raise ValueError(
108                "format must be PKCS8 when encoding is PEM or DER"
109            )
110
111        return self._backend._private_key_bytes(
112            encoding, format, encryption_algorithm, self._evp_pkey, None
113        )
114
115    def _raw_private_bytes(self):
116        buf = self._backend._ffi.new("unsigned char []", _X448_KEY_SIZE)
117        buflen = self._backend._ffi.new("size_t *", _X448_KEY_SIZE)
118        res = self._backend._lib.EVP_PKEY_get_raw_private_key(
119            self._evp_pkey, buf, buflen
120        )
121        self._backend.openssl_assert(res == 1)
122        self._backend.openssl_assert(buflen[0] == _X448_KEY_SIZE)
123        return self._backend._ffi.buffer(buf, _X448_KEY_SIZE)[:]
124