@@ -92,6 +92,85 @@ def test_aes_cbc(self):
9292 self .assertEqual ((ret , written ), (0 , len (o )))
9393 self .assertEqual (h (out_buf ), h (o ))
9494
95+ def test_aes_cbc_with_ecdh_key (self ):
96+ ENCRYPT , DECRYPT , PUBKEY_LEN , _ = 1 , 2 , 33 , True
97+ a_priv = make_cbuffer ('1c6a837d1ac663fdc7f1002327ca38452766eaf4fe3b80ce620bf7cd3f584cf6' )[0 ]
98+ a_pub = make_cbuffer ('03e581be89d1ef8ce11d60746d08e4f8aedf934d1d861dd436042ee2e3b16db918' )[0 ]
99+ b_priv = make_cbuffer ('0b6b3dc90d203d854100110788ac87d43aa00620c9cdb361b281b09022ef4b53' )[0 ]
100+ b_pub = make_cbuffer ('03ff06999ad61c0f3a733b93fc1e6b75ecfb1439b326e840de590a56454f0eeb0d' )[0 ]
101+ iv = make_cbuffer ('bd5d4724243880738e7e8b0c02658700' )[0 ]
102+ label = 'a sample label' .encode ()
103+ payload = 'This is an example response/payload to encrypt' .encode ()
104+ buf = make_cbuffer ('00' * 256 )[0 ]
105+
106+ # Encryption
107+ good_args = [b_priv , len (b_priv ), iv , len (iv ), payload , len (payload ),
108+ a_pub , len (a_pub ), label , len (label ), ENCRYPT , buf , len (buf )]
109+
110+ ret , written = wally_aes_cbc_with_ecdh_key (* good_args )
111+ self .assertEqual (ret , WALLY_OK ) # Make sure good args work
112+ encrypted = make_cbuffer (buf [:written ].hex ())[0 ]
113+
114+ invalid_cases = [
115+ (None , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ ), # NULL privkey
116+ (_ , 0 , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ ), # Empty privkey
117+ (_ , 9 , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ ), # Wrong privkey length
118+ (_ , _ , None , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ ), # NULL IV (enc)
119+ (_ , _ , _ , 0 , _ , _ , _ , _ , _ , _ , _ , _ , _ ), # Empty IV (enc)
120+ (_ , _ , _ , 9 , _ , _ , _ , _ , _ , _ , _ , _ , _ ), # Wrong IV length (enc)
121+ (_ , _ , _ , _ , None , _ , _ , _ , _ , _ , _ , _ , _ ), # NULL payload
122+ (_ , _ , _ , _ , _ , 0 , _ , _ , _ , _ , _ , _ , _ ), # Empty payload
123+ (_ , _ , _ , _ , _ , _ , None , _ , _ , _ , _ , _ , _ ), # NULL pubkey
124+ (_ , _ , _ , _ , _ , _ , _ , 0 , _ , _ , _ , _ , _ ), # Empty pubkey
125+ (_ , _ , _ , _ , _ , _ , _ , 9 , _ , _ , _ , _ , _ ), # Wrong pubkey length
126+ (_ , _ , _ , _ , _ , _ , _ , _ , None , _ , _ , _ , _ ), # NULL label
127+ (_ , _ , _ , _ , _ , _ , _ , _ , _ , 0 , _ , _ , _ ), # Empty label
128+ (_ , _ , _ , _ , _ , _ , _ , _ , _ , _ , 3 , _ , _ ), # Encrypt+Decrypt flags
129+ (_ , _ , _ , _ , _ , _ , _ , _ , _ , _ , 5 , _ , _ ), # Unknown flag
130+ (_ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , None , _ ), # NULL output
131+ (_ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , 0 ), # Zero-length output
132+ ]
133+ for case in invalid_cases :
134+ args = [good_args [i ] if a == _ else a for i , a in enumerate (case )]
135+ self .assertEqual (wally_aes_cbc_with_ecdh_key (* args ), (WALLY_EINVAL , 0 ))
136+
137+ # Test writing up to/beyond the output buffer size
138+ for out_len in range (1 , len (encrypted ) + 16 ):
139+ args = [a for a in good_args ]
140+ args [- 1 ] = out_len
141+ ret = wally_aes_cbc_with_ecdh_key (* args )
142+ self .assertEqual (ret , (WALLY_OK , written )) # returns required length
143+
144+ # Decryption
145+ good_args = [a_priv , len (a_priv ), None , 0 , encrypted , len (encrypted ),
146+ b_pub , len (b_pub ), label , len (label ), DECRYPT , buf , len (buf )]
147+
148+ ret , written = wally_aes_cbc_with_ecdh_key (* good_args )
149+ self .assertEqual (ret , WALLY_OK ) # Make sure good args work
150+ self .assertEqual (buf [:written ], payload )
151+
152+ bad = make_cbuffer ((encrypted [:- 1 ] + b'?' ).hex ())[0 ] # Corrupt the HMAC
153+ bad_len = len (encrypted ) - 1
154+ invalid_cases = [
155+ (_ , _ , iv , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ ), # Non-NULL IV (dec)
156+ (_ , _ , _ , len (iv ), _ , _ , _ , _ , _ , _ , _ , _ , _ ), # Non-zero IV length (dec)
157+ (_ , _ , _ , _ , bad , _ , _ , _ , _ , _ , _ , _ , _ ), # Corrupt HMAC
158+ (_ , _ , _ , _ , _ , bad_len , _ , _ , _ , _ , _ , _ , _ ), # Truncated encrypted data
159+ ]
160+ for case in invalid_cases :
161+ args = [good_args [i ] if a == _ else a for i , a in enumerate (case )]
162+ self .assertEqual (wally_aes_cbc_with_ecdh_key (* args ), (WALLY_EINVAL , 0 ))
163+
164+ # Test writing up to/beyond the output buffer size
165+ for out_len in range (1 , len (payload ) + 16 ):
166+ args = [a for a in good_args ]
167+ args [- 1 ] = out_len
168+ ret , written = wally_aes_cbc_with_ecdh_key (* args )
169+ self .assertEqual (ret , WALLY_OK )
170+ # The output size required includes final padding which is
171+ # stripped if the payload isn't a multiple of the AES block size.
172+ self .assertLessEqual (len (payload ), written )
173+
95174
96175if __name__ == '__main__' :
97176 unittest .main ()
0 commit comments