xref: /qemu/tests/unit/test-crypto-cipher.c (revision e8c5503a)
1 /*
2  * QEMU Crypto cipher algorithms
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 
23 #include "crypto/init.h"
24 #include "crypto/cipher.h"
25 #include "qapi/error.h"
26 
27 typedef struct QCryptoCipherTestData QCryptoCipherTestData;
28 struct QCryptoCipherTestData {
29     const char *path;
30     QCryptoCipherAlgorithm alg;
31     QCryptoCipherMode mode;
32     const char *key;
33     const char *plaintext;
34     const char *ciphertext;
35     const char *iv;
36 };
37 
38 /* AES test data comes from appendix F of:
39  *
40  * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
41  */
42 static QCryptoCipherTestData test_data[] = {
43     {
44         /* NIST F.1.1 ECB-AES128.Encrypt */
45         .path = "/crypto/cipher/aes-ecb-128",
46         .alg = QCRYPTO_CIPHER_ALG_AES_128,
47         .mode = QCRYPTO_CIPHER_MODE_ECB,
48         .key = "2b7e151628aed2a6abf7158809cf4f3c",
49         .plaintext =
50             "6bc1bee22e409f96e93d7e117393172a"
51             "ae2d8a571e03ac9c9eb76fac45af8e51"
52             "30c81c46a35ce411e5fbc1191a0a52ef"
53             "f69f2445df4f9b17ad2b417be66c3710",
54         .ciphertext =
55             "3ad77bb40d7a3660a89ecaf32466ef97"
56             "f5d3d58503b9699de785895a96fdbaaf"
57             "43b1cd7f598ece23881b00e3ed030688"
58             "7b0c785e27e8ad3f8223207104725dd4"
59     },
60     {
61         /* NIST F.1.3 ECB-AES192.Encrypt */
62         .path = "/crypto/cipher/aes-ecb-192",
63         .alg = QCRYPTO_CIPHER_ALG_AES_192,
64         .mode = QCRYPTO_CIPHER_MODE_ECB,
65         .key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
66         .plaintext  =
67             "6bc1bee22e409f96e93d7e117393172a"
68             "ae2d8a571e03ac9c9eb76fac45af8e51"
69             "30c81c46a35ce411e5fbc1191a0a52ef"
70             "f69f2445df4f9b17ad2b417be66c3710",
71         .ciphertext =
72             "bd334f1d6e45f25ff712a214571fa5cc"
73             "974104846d0ad3ad7734ecb3ecee4eef"
74             "ef7afd2270e2e60adce0ba2face6444e"
75             "9a4b41ba738d6c72fb16691603c18e0e"
76     },
77     {
78         /* NIST F.1.5 ECB-AES256.Encrypt */
79         .path = "/crypto/cipher/aes-ecb-256",
80         .alg = QCRYPTO_CIPHER_ALG_AES_256,
81         .mode = QCRYPTO_CIPHER_MODE_ECB,
82         .key =
83             "603deb1015ca71be2b73aef0857d7781"
84             "1f352c073b6108d72d9810a30914dff4",
85         .plaintext  =
86             "6bc1bee22e409f96e93d7e117393172a"
87             "ae2d8a571e03ac9c9eb76fac45af8e51"
88             "30c81c46a35ce411e5fbc1191a0a52ef"
89             "f69f2445df4f9b17ad2b417be66c3710",
90         .ciphertext =
91             "f3eed1bdb5d2a03c064b5a7e3db181f8"
92             "591ccb10d410ed26dc5ba74a31362870"
93             "b6ed21b99ca6f4f9f153e7b1beafed1d"
94             "23304b7a39f9f3ff067d8d8f9e24ecc7",
95     },
96     {
97         /* NIST F.2.1 CBC-AES128.Encrypt */
98         .path = "/crypto/cipher/aes-cbc-128",
99         .alg = QCRYPTO_CIPHER_ALG_AES_128,
100         .mode = QCRYPTO_CIPHER_MODE_CBC,
101         .key = "2b7e151628aed2a6abf7158809cf4f3c",
102         .iv = "000102030405060708090a0b0c0d0e0f",
103         .plaintext  =
104             "6bc1bee22e409f96e93d7e117393172a"
105             "ae2d8a571e03ac9c9eb76fac45af8e51"
106             "30c81c46a35ce411e5fbc1191a0a52ef"
107             "f69f2445df4f9b17ad2b417be66c3710",
108         .ciphertext =
109             "7649abac8119b246cee98e9b12e9197d"
110             "5086cb9b507219ee95db113a917678b2"
111             "73bed6b8e3c1743b7116e69e22229516"
112             "3ff1caa1681fac09120eca307586e1a7",
113     },
114     {
115         /* NIST F.2.3 CBC-AES128.Encrypt */
116         .path = "/crypto/cipher/aes-cbc-192",
117         .alg = QCRYPTO_CIPHER_ALG_AES_192,
118         .mode = QCRYPTO_CIPHER_MODE_CBC,
119         .key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
120         .iv = "000102030405060708090a0b0c0d0e0f",
121         .plaintext  =
122             "6bc1bee22e409f96e93d7e117393172a"
123             "ae2d8a571e03ac9c9eb76fac45af8e51"
124             "30c81c46a35ce411e5fbc1191a0a52ef"
125             "f69f2445df4f9b17ad2b417be66c3710",
126         .ciphertext =
127             "4f021db243bc633d7178183a9fa071e8"
128             "b4d9ada9ad7dedf4e5e738763f69145a"
129             "571b242012fb7ae07fa9baac3df102e0"
130             "08b0e27988598881d920a9e64f5615cd",
131     },
132     {
133         /* NIST F.2.5 CBC-AES128.Encrypt */
134         .path = "/crypto/cipher/aes-cbc-256",
135         .alg = QCRYPTO_CIPHER_ALG_AES_256,
136         .mode = QCRYPTO_CIPHER_MODE_CBC,
137         .key =
138             "603deb1015ca71be2b73aef0857d7781"
139             "1f352c073b6108d72d9810a30914dff4",
140         .iv = "000102030405060708090a0b0c0d0e0f",
141         .plaintext  =
142             "6bc1bee22e409f96e93d7e117393172a"
143             "ae2d8a571e03ac9c9eb76fac45af8e51"
144             "30c81c46a35ce411e5fbc1191a0a52ef"
145             "f69f2445df4f9b17ad2b417be66c3710",
146         .ciphertext =
147             "f58c4c04d6e5f1ba779eabfb5f7bfbd6"
148             "9cfc4e967edb808d679f777bc6702c7d"
149             "39f23369a9d9bacfa530e26304231461"
150             "b2eb05e2c39be9fcda6c19078c6a9d1b",
151     },
152     {
153         /*
154          * Testing 'password' as plaintext fits
155          * in single AES block, and gives identical
156          * ciphertext in ECB and CBC modes
157          */
158         .path = "/crypto/cipher/des-ecb-56-one-block",
159         .alg = QCRYPTO_CIPHER_ALG_DES,
160         .mode = QCRYPTO_CIPHER_MODE_ECB,
161         .key = "80c4a2e691d5b3f7",
162         .plaintext = "70617373776f7264",
163         .ciphertext = "73fa80b66134e403",
164     },
165     {
166         /* See previous comment */
167         .path = "/crypto/cipher/des-cbc-56-one-block",
168         .alg = QCRYPTO_CIPHER_ALG_DES,
169         .mode = QCRYPTO_CIPHER_MODE_CBC,
170         .key = "80c4a2e691d5b3f7",
171         .iv = "0000000000000000",
172         .plaintext = "70617373776f7264",
173         .ciphertext = "73fa80b66134e403",
174     },
175     {
176         .path = "/crypto/cipher/des-ecb-56",
177         .alg = QCRYPTO_CIPHER_ALG_DES,
178         .mode = QCRYPTO_CIPHER_MODE_ECB,
179         .key = "80c4a2e691d5b3f7",
180         .plaintext =
181             "6bc1bee22e409f96e93d7e117393172a"
182             "ae2d8a571e03ac9c9eb76fac45af8e51"
183             "30c81c46a35ce411e5fbc1191a0a52ef"
184             "f69f2445df4f9b17ad2b417be66c3710",
185         .ciphertext =
186             "8f346aaf64eaf24040720d80648c52e7"
187             "aefc616be53ab1a3d301e69d91e01838"
188             "ffd29f1bb5596ad94ea2d8e6196b7f09"
189             "30d8ed0bf2773af36dd82a6280c20926",
190     },
191     {
192         /* Borrowed from linux-kernel crypto/testmgr.h */
193         .path = "/crypto/cipher/3des-cbc",
194         .alg = QCRYPTO_CIPHER_ALG_3DES,
195         .mode = QCRYPTO_CIPHER_MODE_CBC,
196         .key =
197             "e9c0ff2e760b6424444d995a12d640c0"
198             "eac284e81495dbe8",
199         .iv =
200             "7d3388930f93b242",
201         .plaintext =
202             "6f54206f614d796e5320636565727374"
203             "54206f6f4d206e612079655372637465"
204             "20736f54206f614d796e532063656572"
205             "737454206f6f4d206e61207965537263"
206             "746520736f54206f614d796e53206365"
207             "6572737454206f6f4d206e6120796553"
208             "7263746520736f54206f614d796e5320"
209             "63656572737454206f6f4d206e610a79",
210         .ciphertext =
211             "0e2db6973c5633f4671721c76e8ad549"
212             "74b34905c51cd0ed12565c5396b6007d"
213             "9048fcf58d2939cc8ad5351836234ed7"
214             "76d1da0c9467bb048bf2036ca8cfb6ea"
215             "226447aa8f7513bf9fc2c3f0c956c57a"
216             "71632e897b1e12cae25fafd8a4f8c97a"
217             "d6f92131624445a6d6bc5ad32d5443cc"
218             "9ddea570e942458a6bfab19113b0d919",
219     },
220     {
221         /* Borrowed from linux-kernel crypto/testmgr.h */
222         .path = "/crypto/cipher/3des-ecb",
223         .alg = QCRYPTO_CIPHER_ALG_3DES,
224         .mode = QCRYPTO_CIPHER_MODE_ECB,
225         .key =
226             "0123456789abcdef5555555555555555"
227             "fedcba9876543210",
228         .plaintext =
229             "736f6d6564617461",
230         .ciphertext =
231             "18d748e563620572",
232     },
233     {
234         /* Borrowed from linux-kernel crypto/testmgr.h */
235         .path = "/crypto/cipher/3des-ctr",
236         .alg = QCRYPTO_CIPHER_ALG_3DES,
237         .mode = QCRYPTO_CIPHER_MODE_CTR,
238         .key =
239             "9cd6f39cb95a67005a67002dceeb2dce"
240             "ebb45172b451721f",
241         .iv =
242             "ffffffffffffffff",
243         .plaintext =
244             "05ec77fb42d559208b128669f05bcf56"
245             "39ad349f66ea7dc448d3ba0db118e34a"
246             "fe41285c278e11856cf75ec2553ca00b"
247             "9265e970db4fd6b900b41fe649fd442f"
248             "533a8d149863ca5dc1a833a70e9178ec"
249             "77de42d5bc078b12e54cf05b22563980"
250             "6b9f66c950c4af36ba0d947fe34add41"
251             "28b31a8e11f843f75e21553c876e9265"
252             "cc57dba235b900eb72e649d0442fb619"
253             "8d14ff46ca5d24a8339a6d9178c377de"
254             "a108bc07ee71e54cd75b22b51c806bf2"
255             "45c9503baf369960947fc64adda40fb3"
256             "1aed74f8432a5e218813876ef158cc57"
257             "3ea2359c67eb72c549d0bb02b619e04b"
258             "ff46295d248f169a6df45fc3aa3da108"
259             "937aee71d84cd7be01b51ce74ef2452c"
260             "503b82159960cb52c6a930a40f9679ed"
261             "74df432abd048813fa4df15823573e81"
262             "689c67ce51c5ac37bb02957ce04bd246"
263             "29b01b8f16f940f45f26aa3d846f937a"
264             "cd54d8a30abe01e873e74ed1452cb71e"
265             "8215fc47cb5225a9309b629679c074df"
266             "a609bd04ef76fa4dd458238a1d8168f3"
267             "5ace5138ac379e61957cc74bd2a50cb0"
268             "1be275f9402b5f268910846ff659cd54"
269             "3fa30a9d64e873da4ed1b803b71ee148"
270             "fc472e52258c179b62f55cc0ab32a609"
271             "907bef76d94dd4bf068a1de44ff35a2d"
272             "5138836a9e61c853c7ae31a50c977ee2"
273             "75dc402bb2058910fb42f65920543f86"
274             "699d64cf56daad34b803ea7de148d347",
275         .ciphertext =
276             "07c20820721f49ef19cd6f3253052215"
277             "a2852bdb85d2d8b9dd0d1b45cb6911d4"
278             "eabeb2455d0caebea0c127ac659f537e"
279             "afc21bb5b86d360c25c0f86d0b2901da"
280             "1378dc89121243faf612ef8d87627883"
281             "e2be41204c6d351bd10c30cfe2de2b03"
282             "bf4573d4e55995d1b39b276297bdde7f"
283             "a4d23980aa5023f074883da86a18793b"
284             "c4966c8d2240926ed6ad2a1fde63c0e7"
285             "07f72df7b5f3f0cc017c2a9bc210caaa"
286             "fd2b3fc5f3f6fc9b45db53e45bf3c97b"
287             "8e52ffc802b8ac9da10039da3d2d0e01"
288             "097d8d5ebe53b9b08ee7e2966ab278ea"
289             "de238ba5fa5ce3dabf8e316a55d16ab2"
290             "b5466fa5f0eeba1f9f98b0664fd03fa9"
291             "df5f58c4f4ff755c403a097e6e1c97d4"
292             "cce7e771cf0b150871fa0797cde6ca1d"
293             "14280ccf99137af1ebfafa9207de1da1"
294             "d33669fe514d9f2e83374f1f4830ed04"
295             "4da4ef3aca76f41c418f6337782f86a6"
296             "ef417ed2af88ab675271c38ef8269372"
297             "aad60ee70b46b13ab408a9a8a0cf200c"
298             "52bc8b0556b2bc319b74b92929969a50"
299             "dc45dc1aeb0c64d4d3057e5955c3f490"
300             "c2abf89b8adacea1c3f4ad77dd44c8ac"
301             "a3f1c9d2195cb0caa234c1f76cfdac65"
302             "32dc48c4f2006b77f17d76acc031632a"
303             "a53a62c891b10365cb43d106dfc367bc"
304             "dce0cd35ce4965a0527ba70d07a91bb0"
305             "407772c2ea0e3a7846b991b6e73d5142"
306             "fd51b0c62c6313785ceefccfc4700034",
307     },
308     {
309         /* RFC 2144, Appendix B.1 */
310         .path = "/crypto/cipher/cast5-128",
311         .alg = QCRYPTO_CIPHER_ALG_CAST5_128,
312         .mode = QCRYPTO_CIPHER_MODE_ECB,
313         .key = "0123456712345678234567893456789A",
314         .plaintext = "0123456789abcdef",
315         .ciphertext = "238b4fe5847e44b2",
316     },
317     {
318         /* libgcrypt serpent.c */
319         .path = "/crypto/cipher/serpent-128",
320         .alg = QCRYPTO_CIPHER_ALG_SERPENT_128,
321         .mode = QCRYPTO_CIPHER_MODE_ECB,
322         .key = "00000000000000000000000000000000",
323         .plaintext = "d29d576fcea3a3a7ed9099f29273d78e",
324         .ciphertext = "b2288b968ae8b08648d1ce9606fd992d",
325     },
326     {
327         /* libgcrypt serpent.c */
328         .path = "/crypto/cipher/serpent-192",
329         .alg = QCRYPTO_CIPHER_ALG_SERPENT_192,
330         .mode = QCRYPTO_CIPHER_MODE_ECB,
331         .key = "00000000000000000000000000000000"
332                "0000000000000000",
333         .plaintext = "d29d576fceaba3a7ed9899f2927bd78e",
334         .ciphertext = "130e353e1037c22405e8faefb2c3c3e9",
335     },
336     {
337         /* libgcrypt serpent.c */
338         .path = "/crypto/cipher/serpent-256a",
339         .alg = QCRYPTO_CIPHER_ALG_SERPENT_256,
340         .mode = QCRYPTO_CIPHER_MODE_ECB,
341         .key = "00000000000000000000000000000000"
342                "00000000000000000000000000000000",
343         .plaintext = "d095576fcea3e3a7ed98d9f29073d78e",
344         .ciphertext = "b90ee5862de69168f2bdd5125b45472b",
345     },
346     {
347         /* libgcrypt serpent.c */
348         .path = "/crypto/cipher/serpent-256b",
349         .alg = QCRYPTO_CIPHER_ALG_SERPENT_256,
350         .mode = QCRYPTO_CIPHER_MODE_ECB,
351         .key = "00000000000000000000000000000000"
352                "00000000000000000000000000000000",
353         .plaintext = "00000000010000000200000003000000",
354         .ciphertext = "2061a42782bd52ec691ec383b03ba77c",
355     },
356     {
357         /* Twofish paper "Known Answer Test" */
358         .path = "/crypto/cipher/twofish-128",
359         .alg = QCRYPTO_CIPHER_ALG_TWOFISH_128,
360         .mode = QCRYPTO_CIPHER_MODE_ECB,
361         .key = "d491db16e7b1c39e86cb086b789f5419",
362         .plaintext = "019f9809de1711858faac3a3ba20fbc3",
363         .ciphertext = "6363977de839486297e661c6c9d668eb",
364     },
365     {
366         /* Twofish paper "Known Answer Test", I=3 */
367         .path = "/crypto/cipher/twofish-192",
368         .alg = QCRYPTO_CIPHER_ALG_TWOFISH_192,
369         .mode = QCRYPTO_CIPHER_MODE_ECB,
370         .key = "88b2b2706b105e36b446bb6d731a1e88"
371                "efa71f788965bd44",
372         .plaintext = "39da69d6ba4997d585b6dc073ca341b2",
373         .ciphertext = "182b02d81497ea45f9daacdc29193a65",
374     },
375     {
376         /* Twofish paper "Known Answer Test", I=4 */
377         .path = "/crypto/cipher/twofish-256",
378         .alg = QCRYPTO_CIPHER_ALG_TWOFISH_256,
379         .mode = QCRYPTO_CIPHER_MODE_ECB,
380         .key = "d43bb7556ea32e46f2a282b7d45b4e0d"
381                "57ff739d4dc92c1bd7fc01700cc8216f",
382         .plaintext = "90afe91bb288544f2c32dc239b2635e6",
383         .ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa",
384     },
385 #ifdef CONFIG_CRYPTO_SM4
386     {
387         /* SM4, GB/T 32907-2016, Appendix A.1 */
388         .path = "/crypto/cipher/sm4",
389         .alg = QCRYPTO_CIPHER_ALG_SM4,
390         .mode = QCRYPTO_CIPHER_MODE_ECB,
391         .key = "0123456789abcdeffedcba9876543210",
392         .plaintext  =
393             "0123456789abcdeffedcba9876543210",
394         .ciphertext =
395             "681edf34d206965e86b3e94f536e4246",
396     },
397 #endif
398     {
399         /* #1 32 byte key, 32 byte PTX */
400         .path = "/crypto/cipher/aes-xts-128-1",
401         .alg = QCRYPTO_CIPHER_ALG_AES_128,
402         .mode = QCRYPTO_CIPHER_MODE_XTS,
403         .key =
404             "00000000000000000000000000000000"
405             "00000000000000000000000000000000",
406         .iv =
407             "00000000000000000000000000000000",
408         .plaintext =
409             "00000000000000000000000000000000"
410             "00000000000000000000000000000000",
411         .ciphertext =
412             "917cf69ebd68b2ec9b9fe9a3eadda692"
413             "cd43d2f59598ed858c02c2652fbf922e",
414     },
415     {
416         /* #2, 32 byte key, 32 byte PTX */
417         .path = "/crypto/cipher/aes-xts-128-2",
418         .alg = QCRYPTO_CIPHER_ALG_AES_128,
419         .mode = QCRYPTO_CIPHER_MODE_XTS,
420         .key =
421             "11111111111111111111111111111111"
422             "22222222222222222222222222222222",
423         .iv =
424             "33333333330000000000000000000000",
425         .plaintext =
426             "44444444444444444444444444444444"
427             "44444444444444444444444444444444",
428         .ciphertext =
429             "c454185e6a16936e39334038acef838b"
430             "fb186fff7480adc4289382ecd6d394f0",
431     },
432     {
433         /* #5 from xts.7, 32 byte key, 32 byte PTX */
434         .path = "/crypto/cipher/aes-xts-128-3",
435         .alg = QCRYPTO_CIPHER_ALG_AES_128,
436         .mode = QCRYPTO_CIPHER_MODE_XTS,
437         .key =
438             "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0"
439             "bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0",
440         .iv =
441             "9a785634120000000000000000000000",
442         .plaintext =
443             "44444444444444444444444444444444"
444             "44444444444444444444444444444444",
445         .ciphertext =
446             "b01f86f8edc1863706fa8a4253e34f28"
447             "af319de38334870f4dd1f94cbe9832f1",
448     },
449     {
450         /* #4, 32 byte key, 512 byte PTX  */
451         .path = "/crypto/cipher/aes-xts-128-4",
452         .alg = QCRYPTO_CIPHER_ALG_AES_128,
453         .mode = QCRYPTO_CIPHER_MODE_XTS,
454         .key =
455             "27182818284590452353602874713526"
456             "31415926535897932384626433832795",
457         .iv =
458             "00000000000000000000000000000000",
459         .plaintext =
460             "000102030405060708090a0b0c0d0e0f"
461             "101112131415161718191a1b1c1d1e1f"
462             "202122232425262728292a2b2c2d2e2f"
463             "303132333435363738393a3b3c3d3e3f"
464             "404142434445464748494a4b4c4d4e4f"
465             "505152535455565758595a5b5c5d5e5f"
466             "606162636465666768696a6b6c6d6e6f"
467             "707172737475767778797a7b7c7d7e7f"
468             "808182838485868788898a8b8c8d8e8f"
469             "909192939495969798999a9b9c9d9e9f"
470             "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
471             "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
472             "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
473             "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
474             "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
475             "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
476             "000102030405060708090a0b0c0d0e0f"
477             "101112131415161718191a1b1c1d1e1f"
478             "202122232425262728292a2b2c2d2e2f"
479             "303132333435363738393a3b3c3d3e3f"
480             "404142434445464748494a4b4c4d4e4f"
481             "505152535455565758595a5b5c5d5e5f"
482             "606162636465666768696a6b6c6d6e6f"
483             "707172737475767778797a7b7c7d7e7f"
484             "808182838485868788898a8b8c8d8e8f"
485             "909192939495969798999a9b9c9d9e9f"
486             "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
487             "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
488             "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
489             "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
490             "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
491             "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
492         .ciphertext =
493             "27a7479befa1d476489f308cd4cfa6e2"
494             "a96e4bbe3208ff25287dd3819616e89c"
495             "c78cf7f5e543445f8333d8fa7f560000"
496             "05279fa5d8b5e4ad40e736ddb4d35412"
497             "328063fd2aab53e5ea1e0a9f332500a5"
498             "df9487d07a5c92cc512c8866c7e860ce"
499             "93fdf166a24912b422976146ae20ce84"
500             "6bb7dc9ba94a767aaef20c0d61ad0265"
501             "5ea92dc4c4e41a8952c651d33174be51"
502             "a10c421110e6d81588ede82103a252d8"
503             "a750e8768defffed9122810aaeb99f91"
504             "72af82b604dc4b8e51bcb08235a6f434"
505             "1332e4ca60482a4ba1a03b3e65008fc5"
506             "da76b70bf1690db4eae29c5f1badd03c"
507             "5ccf2a55d705ddcd86d449511ceb7ec3"
508             "0bf12b1fa35b913f9f747a8afd1b130e"
509             "94bff94effd01a91735ca1726acd0b19"
510             "7c4e5b03393697e126826fb6bbde8ecc"
511             "1e08298516e2c9ed03ff3c1b7860f6de"
512             "76d4cecd94c8119855ef5297ca67e9f3"
513             "e7ff72b1e99785ca0a7e7720c5b36dc6"
514             "d72cac9574c8cbbc2f801e23e56fd344"
515             "b07f22154beba0f08ce8891e643ed995"
516             "c94d9a69c9f1b5f499027a78572aeebd"
517             "74d20cc39881c213ee770b1010e4bea7"
518             "18846977ae119f7a023ab58cca0ad752"
519             "afe656bb3c17256a9f6e9bf19fdd5a38"
520             "fc82bbe872c5539edb609ef4f79c203e"
521             "bb140f2e583cb2ad15b4aa5b655016a8"
522             "449277dbd477ef2c8d6c017db738b18d"
523             "eb4a427d1923ce3ff262735779a418f2"
524             "0a282df920147beabe421ee5319d0568",
525     },
526     {
527         /* Bad config - cast5-128 has 8 byte block size
528          * which is incompatible with XTS
529          */
530         .path = "/crypto/cipher/cast5-xts-128",
531         .alg = QCRYPTO_CIPHER_ALG_CAST5_128,
532         .mode = QCRYPTO_CIPHER_MODE_XTS,
533         .key =
534             "27182818284590452353602874713526"
535             "31415926535897932384626433832795",
536     },
537     {
538         /* NIST F.5.1 CTR-AES128.Encrypt */
539         .path = "/crypto/cipher/aes-ctr-128",
540         .alg = QCRYPTO_CIPHER_ALG_AES_128,
541         .mode = QCRYPTO_CIPHER_MODE_CTR,
542         .key = "2b7e151628aed2a6abf7158809cf4f3c",
543         .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
544         .plaintext  =
545             "6bc1bee22e409f96e93d7e117393172a"
546             "ae2d8a571e03ac9c9eb76fac45af8e51"
547             "30c81c46a35ce411e5fbc1191a0a52ef"
548             "f69f2445df4f9b17ad2b417be66c3710",
549         .ciphertext =
550             "874d6191b620e3261bef6864990db6ce"
551             "9806f66b7970fdff8617187bb9fffdff"
552             "5ae4df3edbd5d35e5b4f09020db03eab"
553             "1e031dda2fbe03d1792170a0f3009cee",
554     },
555     {
556         /* NIST F.5.3 CTR-AES192.Encrypt */
557         .path = "/crypto/cipher/aes-ctr-192",
558         .alg = QCRYPTO_CIPHER_ALG_AES_192,
559         .mode = QCRYPTO_CIPHER_MODE_CTR,
560         .key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
561         .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
562         .plaintext  =
563             "6bc1bee22e409f96e93d7e117393172a"
564             "ae2d8a571e03ac9c9eb76fac45af8e51"
565             "30c81c46a35ce411e5fbc1191a0a52ef"
566             "f69f2445df4f9b17ad2b417be66c3710",
567         .ciphertext =
568             "1abc932417521ca24f2b0459fe7e6e0b"
569             "090339ec0aa6faefd5ccc2c6f4ce8e94"
570             "1e36b26bd1ebc670d1bd1d665620abf7"
571             "4f78a7f6d29809585a97daec58c6b050",
572     },
573     {
574         /* NIST F.5.5 CTR-AES256.Encrypt */
575         .path = "/crypto/cipher/aes-ctr-256",
576         .alg = QCRYPTO_CIPHER_ALG_AES_256,
577         .mode = QCRYPTO_CIPHER_MODE_CTR,
578         .key = "603deb1015ca71be2b73aef0857d7781"
579                "1f352c073b6108d72d9810a30914dff4",
580         .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
581         .plaintext  =
582             "6bc1bee22e409f96e93d7e117393172a"
583             "ae2d8a571e03ac9c9eb76fac45af8e51"
584             "30c81c46a35ce411e5fbc1191a0a52ef"
585             "f69f2445df4f9b17ad2b417be66c3710",
586         .ciphertext =
587             "601ec313775789a5b7a7f504bbf3d228"
588             "f443e3ca4d62b59aca84e990cacaf5c5"
589             "2b0930daa23de94ce87017ba2d84988d"
590             "dfc9c58db67aada613c2dd08457941a6",
591     }
592 };
593 
594 
595 static inline int unhex(char c)
596 {
597     if (c >= 'a' && c <= 'f') {
598         return 10 + (c - 'a');
599     }
600     if (c >= 'A' && c <= 'F') {
601         return 10 + (c - 'A');
602     }
603     return c - '0';
604 }
605 
606 static inline char hex(int i)
607 {
608     if (i < 10) {
609         return '0' + i;
610     }
611     return 'a' + (i - 10);
612 }
613 
614 static size_t unhex_string(const char *hexstr,
615                            uint8_t **data)
616 {
617     size_t len;
618     size_t i;
619 
620     if (!hexstr) {
621         *data = NULL;
622         return 0;
623     }
624 
625     len = strlen(hexstr);
626     *data = g_new0(uint8_t, len / 2);
627 
628     for (i = 0; i < len; i += 2) {
629         (*data)[i/2] = (unhex(hexstr[i]) << 4) | unhex(hexstr[i+1]);
630     }
631     return len / 2;
632 }
633 
634 static char *hex_string(const uint8_t *bytes,
635                         size_t len)
636 {
637     char *hexstr = g_new0(char, len * 2 + 1);
638     size_t i;
639 
640     for (i = 0; i < len; i++) {
641         hexstr[i*2] = hex((bytes[i] >> 4) & 0xf);
642         hexstr[i*2+1] = hex(bytes[i] & 0xf);
643     }
644     hexstr[len*2] = '\0';
645 
646     return hexstr;
647 }
648 
649 static void test_cipher(const void *opaque)
650 {
651     const QCryptoCipherTestData *data = opaque;
652 
653     QCryptoCipher *cipher;
654     uint8_t *key, *iv = NULL, *ciphertext = NULL,
655         *plaintext = NULL, *outtext = NULL;
656     size_t nkey, niv = 0, nciphertext = 0, nplaintext = 0;
657     char *outtexthex = NULL;
658     size_t ivsize, keysize, blocksize;
659     Error *err = NULL;
660 
661     nkey = unhex_string(data->key, &key);
662     if (data->iv) {
663         niv = unhex_string(data->iv, &iv);
664     }
665     if (data->ciphertext) {
666         nciphertext = unhex_string(data->ciphertext, &ciphertext);
667     }
668     if (data->plaintext) {
669         nplaintext = unhex_string(data->plaintext, &plaintext);
670     }
671 
672     g_assert(nciphertext == nplaintext);
673 
674     outtext = g_new0(uint8_t, nciphertext);
675 
676     cipher = qcrypto_cipher_new(
677         data->alg, data->mode,
678         key, nkey,
679         data->plaintext ? &error_abort : &err);
680     if (data->plaintext) {
681         g_assert(cipher != NULL);
682     } else {
683         error_free_or_abort(&err);
684         g_assert(cipher == NULL);
685         goto cleanup;
686     }
687 
688     keysize = qcrypto_cipher_get_key_len(data->alg);
689     blocksize = qcrypto_cipher_get_block_len(data->alg);
690     ivsize = qcrypto_cipher_get_iv_len(data->alg, data->mode);
691 
692     if (data->mode == QCRYPTO_CIPHER_MODE_XTS) {
693         g_assert_cmpint(keysize * 2, ==, nkey);
694     } else {
695         g_assert_cmpint(keysize, ==, nkey);
696     }
697     g_assert_cmpint(ivsize, ==, niv);
698     if (niv) {
699         g_assert_cmpint(blocksize, ==, niv);
700     }
701 
702     if (iv) {
703         g_assert(qcrypto_cipher_setiv(cipher,
704                                       iv, niv,
705                                       &error_abort) == 0);
706     }
707     g_assert(qcrypto_cipher_encrypt(cipher,
708                                     plaintext,
709                                     outtext,
710                                     nplaintext,
711                                     &error_abort) == 0);
712 
713     outtexthex = hex_string(outtext, nciphertext);
714 
715     g_assert_cmpstr(outtexthex, ==, data->ciphertext);
716 
717     g_free(outtexthex);
718 
719     if (iv) {
720         g_assert(qcrypto_cipher_setiv(cipher,
721                                       iv, niv,
722                                       &error_abort) == 0);
723     }
724     g_assert(qcrypto_cipher_decrypt(cipher,
725                                     ciphertext,
726                                     outtext,
727                                     nplaintext,
728                                     &error_abort) == 0);
729 
730     outtexthex = hex_string(outtext, nplaintext);
731 
732     g_assert_cmpstr(outtexthex, ==, data->plaintext);
733 
734  cleanup:
735     g_free(outtext);
736     g_free(outtexthex);
737     g_free(key);
738     g_free(iv);
739     g_free(ciphertext);
740     g_free(plaintext);
741     qcrypto_cipher_free(cipher);
742 }
743 
744 
745 static void test_cipher_null_iv(void)
746 {
747     QCryptoCipher *cipher;
748     uint8_t key[32] = { 0 };
749     uint8_t plaintext[32] = { 0 };
750     uint8_t ciphertext[32] = { 0 };
751 
752     cipher = qcrypto_cipher_new(
753         QCRYPTO_CIPHER_ALG_AES_256,
754         QCRYPTO_CIPHER_MODE_CBC,
755         key, sizeof(key),
756         &error_abort);
757     g_assert(cipher != NULL);
758 
759     /* Don't call qcrypto_cipher_setiv */
760 
761     qcrypto_cipher_encrypt(cipher,
762                            plaintext,
763                            ciphertext,
764                            sizeof(plaintext),
765                            &error_abort);
766 
767     qcrypto_cipher_free(cipher);
768 }
769 
770 static void test_cipher_short_plaintext(void)
771 {
772     Error *err = NULL;
773     QCryptoCipher *cipher;
774     uint8_t key[32] = { 0 };
775     uint8_t plaintext1[20] = { 0 };
776     uint8_t ciphertext1[20] = { 0 };
777     uint8_t plaintext2[40] = { 0 };
778     uint8_t ciphertext2[40] = { 0 };
779     int ret;
780 
781     cipher = qcrypto_cipher_new(
782         QCRYPTO_CIPHER_ALG_AES_256,
783         QCRYPTO_CIPHER_MODE_CBC,
784         key, sizeof(key),
785         &error_abort);
786     g_assert(cipher != NULL);
787 
788     /* Should report an error as plaintext is shorter
789      * than block size
790      */
791     ret = qcrypto_cipher_encrypt(cipher,
792                                  plaintext1,
793                                  ciphertext1,
794                                  sizeof(plaintext1),
795                                  &err);
796     g_assert(ret == -1);
797     error_free_or_abort(&err);
798 
799     /* Should report an error as plaintext is larger than
800      * block size, but not a multiple of block size
801      */
802     ret = qcrypto_cipher_encrypt(cipher,
803                                  plaintext2,
804                                  ciphertext2,
805                                  sizeof(plaintext2),
806                                  &err);
807     g_assert(ret == -1);
808     error_free_or_abort(&err);
809 
810     qcrypto_cipher_free(cipher);
811 }
812 
813 int main(int argc, char **argv)
814 {
815     size_t i;
816 
817     g_test_init(&argc, &argv, NULL);
818 
819     g_assert(qcrypto_init(NULL) == 0);
820 
821     for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
822         if (qcrypto_cipher_supports(test_data[i].alg, test_data[i].mode)) {
823             g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher);
824         } else {
825             g_printerr("# skip unsupported %s:%s\n",
826                        QCryptoCipherAlgorithm_str(test_data[i].alg),
827                        QCryptoCipherMode_str(test_data[i].mode));
828         }
829     }
830 
831     g_test_add_func("/crypto/cipher/null-iv",
832                     test_cipher_null_iv);
833 
834     g_test_add_func("/crypto/cipher/short-plaintext",
835                     test_cipher_short_plaintext);
836 
837     return g_test_run();
838 }
839