@@ -58,9 +58,16 @@ def copy(self):
5858 """
5959 copy = self .new ("" )
6060
61- _ffi .memmove (copy ._native_object , # pylint: disable=protected-access
62- self ._native_object ,
63- self ._native_size )
61+ if hasattr (self , '_copy' ):
62+ ret = self ._copy (self ._native_object ,
63+ copy ._native_object ) # pylint: disable=protected-access
64+ if ret < 0 : # pragma: no cover
65+ raise WolfCryptError ("Hash copy error (%d)" % ret )
66+ else :
67+ _ffi .memmove (copy ._native_object , # pylint: disable=protected-access
68+ self ._native_object ,
69+ self ._native_size )
70+ copy ._shallow_copy = True # pylint: disable=protected-access
6471
6572 return copy
6673
@@ -87,12 +94,26 @@ def digest(self):
8794
8895 if self ._native_object :
8996 obj = _ffi .new (self ._native_type )
90-
91- _ffi .memmove (obj , self ._native_object , self ._native_size )
92-
93- ret = self ._final (obj , result )
94- if ret < 0 : # pragma: no cover
95- raise WolfCryptError ("Hash finalize error (%d)" % ret )
97+ used_deep_copy = hasattr (self , '_copy' )
98+
99+ if used_deep_copy :
100+ ret = self ._copy (self ._native_object , obj )
101+ if ret < 0 : # pragma: no cover
102+ raise WolfCryptError ("Hash copy error (%d)" % ret )
103+ else :
104+ _ffi .memmove (obj , self ._native_object , self ._native_size )
105+
106+ try :
107+ ret = self ._final (obj , result )
108+ if ret < 0 : # pragma: no cover
109+ raise WolfCryptError ("Hash finalize error (%d)" % ret )
110+ finally :
111+ # Only free when we did a deep copy; memmove'd temps share
112+ # internal resources with self and must not be separately freed.
113+ if used_deep_copy :
114+ delete = getattr (self , '_delete' , None )
115+ if delete :
116+ delete (obj )
96117
97118 return _ffi .buffer (result , self .digest_size )[:]
98119
@@ -117,9 +138,11 @@ class Sha(_Hash):
117138 _native_type = "wc_Sha *"
118139 _native_size = _ffi .sizeof ("wc_Sha" )
119140 _delete = _lib .wc_ShaFree
141+ _copy = _lib .wc_ShaCopy
120142
121143 def __del__ (self ):
122- self ._delete (self ._native_object )
144+ if hasattr (self , '_native_object' ) and not getattr (self , '_shallow_copy' , False ):
145+ self ._delete (self ._native_object )
123146
124147 def _init (self ):
125148 return _lib .wc_InitSha (self ._native_object )
@@ -143,9 +166,11 @@ class Sha256(_Hash):
143166 _native_type = "wc_Sha256 *"
144167 _native_size = _ffi .sizeof ("wc_Sha256" )
145168 _delete = _lib .wc_Sha256Free
169+ _copy = _lib .wc_Sha256Copy
146170
147171 def __del__ (self ):
148- self ._delete (self ._native_object )
172+ if hasattr (self , '_native_object' ) and not getattr (self , '_shallow_copy' , False ):
173+ self ._delete (self ._native_object )
149174
150175 def _init (self ):
151176 return _lib .wc_InitSha256 (self ._native_object )
@@ -169,9 +194,11 @@ class Sha384(_Hash):
169194 _native_type = "wc_Sha384 *"
170195 _native_size = _ffi .sizeof ("wc_Sha384" )
171196 _delete = _lib .wc_Sha384Free
197+ _copy = _lib .wc_Sha384Copy
172198
173199 def __del__ (self ):
174- self ._delete (self ._native_object )
200+ if hasattr (self , '_native_object' ) and not getattr (self , '_shallow_copy' , False ):
201+ self ._delete (self ._native_object )
175202
176203 def _init (self ):
177204 return _lib .wc_InitSha384 (self ._native_object )
@@ -195,9 +222,11 @@ class Sha512(_Hash):
195222 _native_type = "wc_Sha512 *"
196223 _native_size = _ffi .sizeof ("wc_Sha512" )
197224 _delete = _lib .wc_Sha512Free
225+ _copy = _lib .wc_Sha512Copy
198226
199227 def __del__ (self ):
200- self ._delete (self ._native_object )
228+ if hasattr (self , '_native_object' ) and not getattr (self , '_shallow_copy' , False ):
229+ self ._delete (self ._native_object )
201230
202231 def _init (self ):
203232 return _lib .wc_InitSha512 (self ._native_object )
@@ -232,14 +261,24 @@ class Sha3(_Hash):
232261 64 : _lib .wc_Sha3_512_Free ,
233262 }
234263
264+ _SHA3_COPY = {
265+ 28 : _lib .wc_Sha3_224_Copy ,
266+ 32 : _lib .wc_Sha3_256_Copy ,
267+ 48 : _lib .wc_Sha3_384_Copy ,
268+ 64 : _lib .wc_Sha3_512_Copy ,
269+ }
270+
235271 def __del__ (self ):
236- if hasattr (self , '_delete' ):
272+ if (hasattr (self , '_native_object' )
273+ and not getattr (self , '_shallow_copy' , False )
274+ and getattr (self , '_delete' , None )):
237275 self ._delete (self ._native_object )
238276
239277 def __init__ (self , string = None , size = SHA3_384_DIGEST_SIZE ): # pylint: disable=W0231
240278 self ._native_object = _ffi .new (self ._native_type )
241279 self .digest_size = size
242280 self ._delete = self ._SHA3_FREE .get (size )
281+ self ._copy = self ._SHA3_COPY .get (size )
243282 ret = self ._init ()
244283 if ret < 0 : # pragma: no cover
245284 raise WolfCryptError ("Sha3 init error (%d)" % ret )
@@ -252,7 +291,13 @@ def new(cls, string=None, size=SHA3_384_DIGEST_SIZE):
252291
253292 def copy (self ):
254293 c = Sha3 (size = self .digest_size )
255- _ffi .memmove (c ._native_object , self ._native_object , self ._native_size )
294+ if self ._copy :
295+ ret = self ._copy (self ._native_object , c ._native_object )
296+ if ret < 0 : # pragma: no cover
297+ raise WolfCryptError ("Hash copy error (%d)" % ret )
298+ else :
299+ _ffi .memmove (c ._native_object , self ._native_object , self ._native_size )
300+ c ._shallow_copy = True
256301 return c
257302
258303 def _init (self ):
@@ -316,7 +361,8 @@ class _Hmac(_Hash):
316361 _delete = _lib .wc_HmacFree
317362
318363 def __del__ (self ):
319- self ._delete (self ._native_object )
364+ if hasattr (self , '_native_object' ) and not getattr (self , '_shallow_copy' , False ):
365+ self ._delete (self ._native_object )
320366
321367 def __init__ (self , key , string = None ): # pylint: disable=W0231
322368 key = t2b (key )
0 commit comments