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.exceptions import InvalidSignature 9from cryptography.hazmat.backends.openssl.utils import ( 10 _calculate_digest_and_algorithm, _check_not_prehashed, 11 _warn_sign_verify_deprecated 12) 13from cryptography.hazmat.primitives import hashes, serialization 14from cryptography.hazmat.primitives.asymmetric import ( 15 AsymmetricSignatureContext, AsymmetricVerificationContext, dsa 16) 17 18 19def _dsa_sig_sign(backend, private_key, data): 20 sig_buf_len = backend._lib.DSA_size(private_key._dsa_cdata) 21 sig_buf = backend._ffi.new("unsigned char[]", sig_buf_len) 22 buflen = backend._ffi.new("unsigned int *") 23 24 # The first parameter passed to DSA_sign is unused by OpenSSL but 25 # must be an integer. 26 res = backend._lib.DSA_sign( 27 0, data, len(data), sig_buf, buflen, private_key._dsa_cdata 28 ) 29 backend.openssl_assert(res == 1) 30 backend.openssl_assert(buflen[0]) 31 32 return backend._ffi.buffer(sig_buf)[:buflen[0]] 33 34 35def _dsa_sig_verify(backend, public_key, signature, data): 36 # The first parameter passed to DSA_verify is unused by OpenSSL but 37 # must be an integer. 38 res = backend._lib.DSA_verify( 39 0, data, len(data), signature, len(signature), public_key._dsa_cdata 40 ) 41 42 if res != 1: 43 backend._consume_errors() 44 raise InvalidSignature 45 46 47@utils.register_interface(AsymmetricVerificationContext) 48class _DSAVerificationContext(object): 49 def __init__(self, backend, public_key, signature, algorithm): 50 self._backend = backend 51 self._public_key = public_key 52 self._signature = signature 53 self._algorithm = algorithm 54 55 self._hash_ctx = hashes.Hash(self._algorithm, self._backend) 56 57 def update(self, data): 58 self._hash_ctx.update(data) 59 60 def verify(self): 61 data_to_verify = self._hash_ctx.finalize() 62 63 _dsa_sig_verify( 64 self._backend, self._public_key, self._signature, data_to_verify 65 ) 66 67 68@utils.register_interface(AsymmetricSignatureContext) 69class _DSASignatureContext(object): 70 def __init__(self, backend, private_key, algorithm): 71 self._backend = backend 72 self._private_key = private_key 73 self._algorithm = algorithm 74 self._hash_ctx = hashes.Hash(self._algorithm, self._backend) 75 76 def update(self, data): 77 self._hash_ctx.update(data) 78 79 def finalize(self): 80 data_to_sign = self._hash_ctx.finalize() 81 return _dsa_sig_sign(self._backend, self._private_key, data_to_sign) 82 83 84@utils.register_interface(dsa.DSAParametersWithNumbers) 85class _DSAParameters(object): 86 def __init__(self, backend, dsa_cdata): 87 self._backend = backend 88 self._dsa_cdata = dsa_cdata 89 90 def parameter_numbers(self): 91 p = self._backend._ffi.new("BIGNUM **") 92 q = self._backend._ffi.new("BIGNUM **") 93 g = self._backend._ffi.new("BIGNUM **") 94 self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) 95 self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) 96 self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) 97 self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) 98 return dsa.DSAParameterNumbers( 99 p=self._backend._bn_to_int(p[0]), 100 q=self._backend._bn_to_int(q[0]), 101 g=self._backend._bn_to_int(g[0]) 102 ) 103 104 def generate_private_key(self): 105 return self._backend.generate_dsa_private_key(self) 106 107 108@utils.register_interface(dsa.DSAPrivateKeyWithSerialization) 109class _DSAPrivateKey(object): 110 def __init__(self, backend, dsa_cdata, evp_pkey): 111 self._backend = backend 112 self._dsa_cdata = dsa_cdata 113 self._evp_pkey = evp_pkey 114 115 p = self._backend._ffi.new("BIGNUM **") 116 self._backend._lib.DSA_get0_pqg( 117 dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL 118 ) 119 self._backend.openssl_assert(p[0] != backend._ffi.NULL) 120 self._key_size = self._backend._lib.BN_num_bits(p[0]) 121 122 key_size = utils.read_only_property("_key_size") 123 124 def signer(self, signature_algorithm): 125 _warn_sign_verify_deprecated() 126 _check_not_prehashed(signature_algorithm) 127 return _DSASignatureContext(self._backend, self, signature_algorithm) 128 129 def private_numbers(self): 130 p = self._backend._ffi.new("BIGNUM **") 131 q = self._backend._ffi.new("BIGNUM **") 132 g = self._backend._ffi.new("BIGNUM **") 133 pub_key = self._backend._ffi.new("BIGNUM **") 134 priv_key = self._backend._ffi.new("BIGNUM **") 135 self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) 136 self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) 137 self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) 138 self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) 139 self._backend._lib.DSA_get0_key(self._dsa_cdata, pub_key, priv_key) 140 self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) 141 self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) 142 return dsa.DSAPrivateNumbers( 143 public_numbers=dsa.DSAPublicNumbers( 144 parameter_numbers=dsa.DSAParameterNumbers( 145 p=self._backend._bn_to_int(p[0]), 146 q=self._backend._bn_to_int(q[0]), 147 g=self._backend._bn_to_int(g[0]) 148 ), 149 y=self._backend._bn_to_int(pub_key[0]) 150 ), 151 x=self._backend._bn_to_int(priv_key[0]) 152 ) 153 154 def public_key(self): 155 dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) 156 self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) 157 dsa_cdata = self._backend._ffi.gc( 158 dsa_cdata, self._backend._lib.DSA_free 159 ) 160 pub_key = self._backend._ffi.new("BIGNUM **") 161 self._backend._lib.DSA_get0_key( 162 self._dsa_cdata, pub_key, self._backend._ffi.NULL 163 ) 164 self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) 165 pub_key_dup = self._backend._lib.BN_dup(pub_key[0]) 166 res = self._backend._lib.DSA_set0_key( 167 dsa_cdata, pub_key_dup, self._backend._ffi.NULL 168 ) 169 self._backend.openssl_assert(res == 1) 170 evp_pkey = self._backend._dsa_cdata_to_evp_pkey(dsa_cdata) 171 return _DSAPublicKey(self._backend, dsa_cdata, evp_pkey) 172 173 def parameters(self): 174 dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) 175 self._backend.openssl_assert(dsa_cdata != self._backend._ffi.NULL) 176 dsa_cdata = self._backend._ffi.gc( 177 dsa_cdata, self._backend._lib.DSA_free 178 ) 179 return _DSAParameters(self._backend, dsa_cdata) 180 181 def private_bytes(self, encoding, format, encryption_algorithm): 182 return self._backend._private_key_bytes( 183 encoding, 184 format, 185 encryption_algorithm, 186 self._evp_pkey, 187 self._dsa_cdata 188 ) 189 190 def sign(self, data, algorithm): 191 data, algorithm = _calculate_digest_and_algorithm( 192 self._backend, data, algorithm 193 ) 194 return _dsa_sig_sign(self._backend, self, data) 195 196 197@utils.register_interface(dsa.DSAPublicKeyWithSerialization) 198class _DSAPublicKey(object): 199 def __init__(self, backend, dsa_cdata, evp_pkey): 200 self._backend = backend 201 self._dsa_cdata = dsa_cdata 202 self._evp_pkey = evp_pkey 203 p = self._backend._ffi.new("BIGNUM **") 204 self._backend._lib.DSA_get0_pqg( 205 dsa_cdata, p, self._backend._ffi.NULL, self._backend._ffi.NULL 206 ) 207 self._backend.openssl_assert(p[0] != backend._ffi.NULL) 208 self._key_size = self._backend._lib.BN_num_bits(p[0]) 209 210 key_size = utils.read_only_property("_key_size") 211 212 def verifier(self, signature, signature_algorithm): 213 _warn_sign_verify_deprecated() 214 utils._check_bytes("signature", signature) 215 216 _check_not_prehashed(signature_algorithm) 217 return _DSAVerificationContext( 218 self._backend, self, signature, signature_algorithm 219 ) 220 221 def public_numbers(self): 222 p = self._backend._ffi.new("BIGNUM **") 223 q = self._backend._ffi.new("BIGNUM **") 224 g = self._backend._ffi.new("BIGNUM **") 225 pub_key = self._backend._ffi.new("BIGNUM **") 226 self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) 227 self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) 228 self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) 229 self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) 230 self._backend._lib.DSA_get0_key( 231 self._dsa_cdata, pub_key, self._backend._ffi.NULL 232 ) 233 self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) 234 return dsa.DSAPublicNumbers( 235 parameter_numbers=dsa.DSAParameterNumbers( 236 p=self._backend._bn_to_int(p[0]), 237 q=self._backend._bn_to_int(q[0]), 238 g=self._backend._bn_to_int(g[0]) 239 ), 240 y=self._backend._bn_to_int(pub_key[0]) 241 ) 242 243 def parameters(self): 244 dsa_cdata = self._backend._lib.DSAparams_dup(self._dsa_cdata) 245 dsa_cdata = self._backend._ffi.gc( 246 dsa_cdata, self._backend._lib.DSA_free 247 ) 248 return _DSAParameters(self._backend, dsa_cdata) 249 250 def public_bytes(self, encoding, format): 251 if format is serialization.PublicFormat.PKCS1: 252 raise ValueError( 253 "DSA public keys do not support PKCS1 serialization" 254 ) 255 256 return self._backend._public_key_bytes( 257 encoding, 258 format, 259 self, 260 self._evp_pkey, 261 None 262 ) 263 264 def verify(self, signature, data, algorithm): 265 data, algorithm = _calculate_digest_and_algorithm( 266 self._backend, data, algorithm 267 ) 268 return _dsa_sig_verify(self._backend, self, signature, data) 269