@@ -12,6 +12,8 @@ use pyo3::IntoPy;
12
12
struct CipherContext {
13
13
ctx : openssl:: cipher_ctx:: CipherCtx ,
14
14
py_mode : pyo3:: PyObject ,
15
+ side : openssl:: symm:: Mode ,
16
+ update_nonce_allowed : bool ,
15
17
}
16
18
17
19
impl CipherContext {
@@ -41,6 +43,7 @@ impl CipherContext {
41
43
}
42
44
} ;
43
45
46
+ let mut update_nonce_allowed = false ;
44
47
let iv_nonce = if mode. is_instance ( types:: MODE_WITH_INITIALIZATION_VECTOR . get ( py) ?) ? {
45
48
Some (
46
49
mode. getattr ( pyo3:: intern!( py, "initialization_vector" ) ) ?
@@ -52,11 +55,13 @@ impl CipherContext {
52
55
. extract :: < CffiBuf < ' _ > > ( ) ?,
53
56
)
54
57
} else if mode. is_instance ( types:: MODE_WITH_NONCE . get ( py) ?) ? {
58
+ update_nonce_allowed = true ;
55
59
Some (
56
60
mode. getattr ( pyo3:: intern!( py, "nonce" ) ) ?
57
61
. extract :: < CffiBuf < ' _ > > ( ) ?,
58
62
)
59
63
} else if algorithm. is_instance ( types:: CHACHA20 . get ( py) ?) ? {
64
+ update_nonce_allowed = true ;
60
65
Some (
61
66
algorithm
62
67
. getattr ( pyo3:: intern!( py, "nonce" ) ) ?
@@ -111,9 +116,36 @@ impl CipherContext {
111
116
Ok ( CipherContext {
112
117
ctx,
113
118
py_mode : mode. into ( ) ,
119
+ side,
120
+ update_nonce_allowed,
114
121
} )
115
122
}
116
123
124
+ fn update_nonce ( & mut self , nonce : CffiBuf < ' _ > ) -> CryptographyResult < ( ) > {
125
+ if !self . update_nonce_allowed {
126
+ return Err ( CryptographyError :: from (
127
+ exceptions:: UnsupportedAlgorithm :: new_err ( (
128
+ "This algorithm or mode does not support resetting the nonce." ,
129
+ exceptions:: Reasons :: UNSUPPORTED_CIPHER ,
130
+ ) ) ,
131
+ ) ) ;
132
+ }
133
+ if nonce. as_bytes ( ) . len ( ) != self . ctx . iv_length ( ) {
134
+ return Err ( CryptographyError :: from (
135
+ pyo3:: exceptions:: PyValueError :: new_err ( format ! (
136
+ "Nonce must be {} bytes long" ,
137
+ self . ctx. iv_length( )
138
+ ) ) ,
139
+ ) ) ;
140
+ }
141
+ let init_op = match self . side {
142
+ openssl:: symm:: Mode :: Encrypt => openssl:: cipher_ctx:: CipherCtxRef :: encrypt_init,
143
+ openssl:: symm:: Mode :: Decrypt => openssl:: cipher_ctx:: CipherCtxRef :: decrypt_init,
144
+ } ;
145
+ init_op ( & mut self . ctx , None , None , Some ( nonce. as_bytes ( ) ) ) ?;
146
+ Ok ( ( ) )
147
+ }
148
+
117
149
fn update < ' p > (
118
150
& mut self ,
119
151
py : pyo3:: Python < ' p > ,
@@ -234,6 +266,10 @@ impl PyCipherContext {
234
266
get_mut_ctx ( self . ctx . as_mut ( ) ) ?. update ( py, buf. as_bytes ( ) )
235
267
}
236
268
269
+ fn update_nonce ( & mut self , nonce : CffiBuf < ' _ > ) -> CryptographyResult < ( ) > {
270
+ get_mut_ctx ( self . ctx . as_mut ( ) ) ?. update_nonce ( nonce)
271
+ }
272
+
237
273
fn update_into (
238
274
& mut self ,
239
275
py : pyo3:: Python < ' _ > ,
@@ -338,6 +374,10 @@ impl PyAEADEncryptionContext {
338
374
} ) ?
339
375
. clone_ref ( py) )
340
376
}
377
+
378
+ fn update_nonce ( & mut self , nonce : CffiBuf < ' _ > ) -> CryptographyResult < ( ) > {
379
+ get_mut_ctx ( self . ctx . as_mut ( ) ) ?. update_nonce ( nonce)
380
+ }
341
381
}
342
382
343
383
#[ pyo3:: prelude:: pymethods]
@@ -466,6 +506,10 @@ impl PyAEADDecryptionContext {
466
506
self . ctx = None ;
467
507
Ok ( result)
468
508
}
509
+
510
+ fn update_nonce ( & mut self , nonce : CffiBuf < ' _ > ) -> CryptographyResult < ( ) > {
511
+ get_mut_ctx ( self . ctx . as_mut ( ) ) ?. update_nonce ( nonce)
512
+ }
469
513
}
470
514
471
515
#[ pyo3:: prelude:: pyfunction]
0 commit comments