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