qemu/tests/test-crypto-cipher.c
<<
>>
Prefs
   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 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
  27typedef struct QCryptoCipherTestData QCryptoCipherTestData;
  28struct 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 */
  42static 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        .path = "/crypto/cipher/des-rfb-ecb-56",
 154        .alg = QCRYPTO_CIPHER_ALG_DES_RFB,
 155        .mode = QCRYPTO_CIPHER_MODE_ECB,
 156        .key = "0123456789abcdef",
 157        .plaintext =
 158            "6bc1bee22e409f96e93d7e117393172a"
 159            "ae2d8a571e03ac9c9eb76fac45af8e51"
 160            "30c81c46a35ce411e5fbc1191a0a52ef"
 161            "f69f2445df4f9b17ad2b417be66c3710",
 162        .ciphertext =
 163            "8f346aaf64eaf24040720d80648c52e7"
 164            "aefc616be53ab1a3d301e69d91e01838"
 165            "ffd29f1bb5596ad94ea2d8e6196b7f09"
 166            "30d8ed0bf2773af36dd82a6280c20926",
 167    },
 168    {
 169        /* RFC 2144, Appendix B.1 */
 170        .path = "/crypto/cipher/cast5-128",
 171        .alg = QCRYPTO_CIPHER_ALG_CAST5_128,
 172        .mode = QCRYPTO_CIPHER_MODE_ECB,
 173        .key = "0123456712345678234567893456789A",
 174        .plaintext = "0123456789abcdef",
 175        .ciphertext = "238b4fe5847e44b2",
 176    },
 177    {
 178        /* libgcrypt serpent.c */
 179        .path = "/crypto/cipher/serpent-128",
 180        .alg = QCRYPTO_CIPHER_ALG_SERPENT_128,
 181        .mode = QCRYPTO_CIPHER_MODE_ECB,
 182        .key = "00000000000000000000000000000000",
 183        .plaintext = "d29d576fcea3a3a7ed9099f29273d78e",
 184        .ciphertext = "b2288b968ae8b08648d1ce9606fd992d",
 185    },
 186    {
 187        /* libgcrypt serpent.c */
 188        .path = "/crypto/cipher/serpent-192",
 189        .alg = QCRYPTO_CIPHER_ALG_SERPENT_192,
 190        .mode = QCRYPTO_CIPHER_MODE_ECB,
 191        .key = "00000000000000000000000000000000"
 192               "0000000000000000",
 193        .plaintext = "d29d576fceaba3a7ed9899f2927bd78e",
 194        .ciphertext = "130e353e1037c22405e8faefb2c3c3e9",
 195    },
 196    {
 197        /* libgcrypt serpent.c */
 198        .path = "/crypto/cipher/serpent-256a",
 199        .alg = QCRYPTO_CIPHER_ALG_SERPENT_256,
 200        .mode = QCRYPTO_CIPHER_MODE_ECB,
 201        .key = "00000000000000000000000000000000"
 202               "00000000000000000000000000000000",
 203        .plaintext = "d095576fcea3e3a7ed98d9f29073d78e",
 204        .ciphertext = "b90ee5862de69168f2bdd5125b45472b",
 205    },
 206    {
 207        /* libgcrypt serpent.c */
 208        .path = "/crypto/cipher/serpent-256b",
 209        .alg = QCRYPTO_CIPHER_ALG_SERPENT_256,
 210        .mode = QCRYPTO_CIPHER_MODE_ECB,
 211        .key = "00000000000000000000000000000000"
 212               "00000000000000000000000000000000",
 213        .plaintext = "00000000010000000200000003000000",
 214        .ciphertext = "2061a42782bd52ec691ec383b03ba77c",
 215    },
 216    {
 217        /* Twofish paper "Known Answer Test" */
 218        .path = "/crypto/cipher/twofish-128",
 219        .alg = QCRYPTO_CIPHER_ALG_TWOFISH_128,
 220        .mode = QCRYPTO_CIPHER_MODE_ECB,
 221        .key = "d491db16e7b1c39e86cb086b789f5419",
 222        .plaintext = "019f9809de1711858faac3a3ba20fbc3",
 223        .ciphertext = "6363977de839486297e661c6c9d668eb",
 224    },
 225    {
 226        /* Twofish paper "Known Answer Test", I=3 */
 227        .path = "/crypto/cipher/twofish-192",
 228        .alg = QCRYPTO_CIPHER_ALG_TWOFISH_192,
 229        .mode = QCRYPTO_CIPHER_MODE_ECB,
 230        .key = "88b2b2706b105e36b446bb6d731a1e88"
 231               "efa71f788965bd44",
 232        .plaintext = "39da69d6ba4997d585b6dc073ca341b2",
 233        .ciphertext = "182b02d81497ea45f9daacdc29193a65",
 234    },
 235    {
 236        /* Twofish paper "Known Answer Test", I=4 */
 237        .path = "/crypto/cipher/twofish-256",
 238        .alg = QCRYPTO_CIPHER_ALG_TWOFISH_256,
 239        .mode = QCRYPTO_CIPHER_MODE_ECB,
 240        .key = "d43bb7556ea32e46f2a282b7d45b4e0d"
 241               "57ff739d4dc92c1bd7fc01700cc8216f",
 242        .plaintext = "90afe91bb288544f2c32dc239b2635e6",
 243        .ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa",
 244    },
 245    {
 246        /* #1 32 byte key, 32 byte PTX */
 247        .path = "/crypto/cipher/aes-xts-128-1",
 248        .alg = QCRYPTO_CIPHER_ALG_AES_128,
 249        .mode = QCRYPTO_CIPHER_MODE_XTS,
 250        .key =
 251            "00000000000000000000000000000000"
 252            "00000000000000000000000000000000",
 253        .iv =
 254            "00000000000000000000000000000000",
 255        .plaintext =
 256            "00000000000000000000000000000000"
 257            "00000000000000000000000000000000",
 258        .ciphertext =
 259            "917cf69ebd68b2ec9b9fe9a3eadda692"
 260            "cd43d2f59598ed858c02c2652fbf922e",
 261    },
 262    {
 263        /* #2, 32 byte key, 32 byte PTX */
 264        .path = "/crypto/cipher/aes-xts-128-2",
 265        .alg = QCRYPTO_CIPHER_ALG_AES_128,
 266        .mode = QCRYPTO_CIPHER_MODE_XTS,
 267        .key =
 268            "11111111111111111111111111111111"
 269            "22222222222222222222222222222222",
 270        .iv =
 271            "33333333330000000000000000000000",
 272        .plaintext =
 273            "44444444444444444444444444444444"
 274            "44444444444444444444444444444444",
 275        .ciphertext =
 276            "c454185e6a16936e39334038acef838b"
 277            "fb186fff7480adc4289382ecd6d394f0",
 278    },
 279    {
 280        /* #5 from xts.7, 32 byte key, 32 byte PTX */
 281        .path = "/crypto/cipher/aes-xts-128-3",
 282        .alg = QCRYPTO_CIPHER_ALG_AES_128,
 283        .mode = QCRYPTO_CIPHER_MODE_XTS,
 284        .key =
 285            "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0"
 286            "bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0",
 287        .iv =
 288            "9a785634120000000000000000000000",
 289        .plaintext =
 290            "44444444444444444444444444444444"
 291            "44444444444444444444444444444444",
 292        .ciphertext =
 293            "b01f86f8edc1863706fa8a4253e34f28"
 294            "af319de38334870f4dd1f94cbe9832f1",
 295    },
 296    {
 297        /* #4, 32 byte key, 512 byte PTX  */
 298        .path = "/crypto/cipher/aes-xts-128-4",
 299        .alg = QCRYPTO_CIPHER_ALG_AES_128,
 300        .mode = QCRYPTO_CIPHER_MODE_XTS,
 301        .key =
 302            "27182818284590452353602874713526"
 303            "31415926535897932384626433832795",
 304        .iv =
 305            "00000000000000000000000000000000",
 306        .plaintext =
 307            "000102030405060708090a0b0c0d0e0f"
 308            "101112131415161718191a1b1c1d1e1f"
 309            "202122232425262728292a2b2c2d2e2f"
 310            "303132333435363738393a3b3c3d3e3f"
 311            "404142434445464748494a4b4c4d4e4f"
 312            "505152535455565758595a5b5c5d5e5f"
 313            "606162636465666768696a6b6c6d6e6f"
 314            "707172737475767778797a7b7c7d7e7f"
 315            "808182838485868788898a8b8c8d8e8f"
 316            "909192939495969798999a9b9c9d9e9f"
 317            "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
 318            "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
 319            "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
 320            "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
 321            "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
 322            "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
 323            "000102030405060708090a0b0c0d0e0f"
 324            "101112131415161718191a1b1c1d1e1f"
 325            "202122232425262728292a2b2c2d2e2f"
 326            "303132333435363738393a3b3c3d3e3f"
 327            "404142434445464748494a4b4c4d4e4f"
 328            "505152535455565758595a5b5c5d5e5f"
 329            "606162636465666768696a6b6c6d6e6f"
 330            "707172737475767778797a7b7c7d7e7f"
 331            "808182838485868788898a8b8c8d8e8f"
 332            "909192939495969798999a9b9c9d9e9f"
 333            "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
 334            "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
 335            "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
 336            "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
 337            "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
 338            "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
 339        .ciphertext =
 340            "27a7479befa1d476489f308cd4cfa6e2"
 341            "a96e4bbe3208ff25287dd3819616e89c"
 342            "c78cf7f5e543445f8333d8fa7f560000"
 343            "05279fa5d8b5e4ad40e736ddb4d35412"
 344            "328063fd2aab53e5ea1e0a9f332500a5"
 345            "df9487d07a5c92cc512c8866c7e860ce"
 346            "93fdf166a24912b422976146ae20ce84"
 347            "6bb7dc9ba94a767aaef20c0d61ad0265"
 348            "5ea92dc4c4e41a8952c651d33174be51"
 349            "a10c421110e6d81588ede82103a252d8"
 350            "a750e8768defffed9122810aaeb99f91"
 351            "72af82b604dc4b8e51bcb08235a6f434"
 352            "1332e4ca60482a4ba1a03b3e65008fc5"
 353            "da76b70bf1690db4eae29c5f1badd03c"
 354            "5ccf2a55d705ddcd86d449511ceb7ec3"
 355            "0bf12b1fa35b913f9f747a8afd1b130e"
 356            "94bff94effd01a91735ca1726acd0b19"
 357            "7c4e5b03393697e126826fb6bbde8ecc"
 358            "1e08298516e2c9ed03ff3c1b7860f6de"
 359            "76d4cecd94c8119855ef5297ca67e9f3"
 360            "e7ff72b1e99785ca0a7e7720c5b36dc6"
 361            "d72cac9574c8cbbc2f801e23e56fd344"
 362            "b07f22154beba0f08ce8891e643ed995"
 363            "c94d9a69c9f1b5f499027a78572aeebd"
 364            "74d20cc39881c213ee770b1010e4bea7"
 365            "18846977ae119f7a023ab58cca0ad752"
 366            "afe656bb3c17256a9f6e9bf19fdd5a38"
 367            "fc82bbe872c5539edb609ef4f79c203e"
 368            "bb140f2e583cb2ad15b4aa5b655016a8"
 369            "449277dbd477ef2c8d6c017db738b18d"
 370            "eb4a427d1923ce3ff262735779a418f2"
 371            "0a282df920147beabe421ee5319d0568",
 372    },
 373    {
 374        /* Bad config - cast5-128 has 8 byte block size
 375         * which is incompatible with XTS
 376         */
 377        .path = "/crypto/cipher/cast5-xts-128",
 378        .alg = QCRYPTO_CIPHER_ALG_CAST5_128,
 379        .mode = QCRYPTO_CIPHER_MODE_XTS,
 380        .key =
 381            "27182818284590452353602874713526"
 382            "31415926535897932384626433832795",
 383    },
 384    {
 385        /* NIST F.5.1 CTR-AES128.Encrypt */
 386        .path = "/crypto/cipher/aes-ctr-128",
 387        .alg = QCRYPTO_CIPHER_ALG_AES_128,
 388        .mode = QCRYPTO_CIPHER_MODE_CTR,
 389        .key = "2b7e151628aed2a6abf7158809cf4f3c",
 390        .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
 391        .plaintext  =
 392            "6bc1bee22e409f96e93d7e117393172a"
 393            "ae2d8a571e03ac9c9eb76fac45af8e51"
 394            "30c81c46a35ce411e5fbc1191a0a52ef"
 395            "f69f2445df4f9b17ad2b417be66c3710",
 396        .ciphertext =
 397            "874d6191b620e3261bef6864990db6ce"
 398            "9806f66b7970fdff8617187bb9fffdff"
 399            "5ae4df3edbd5d35e5b4f09020db03eab"
 400            "1e031dda2fbe03d1792170a0f3009cee",
 401    },
 402    {
 403        /* NIST F.5.3 CTR-AES192.Encrypt */
 404        .path = "/crypto/cipher/aes-ctr-192",
 405        .alg = QCRYPTO_CIPHER_ALG_AES_192,
 406        .mode = QCRYPTO_CIPHER_MODE_CTR,
 407        .key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
 408        .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
 409        .plaintext  =
 410            "6bc1bee22e409f96e93d7e117393172a"
 411            "ae2d8a571e03ac9c9eb76fac45af8e51"
 412            "30c81c46a35ce411e5fbc1191a0a52ef"
 413            "f69f2445df4f9b17ad2b417be66c3710",
 414        .ciphertext =
 415            "1abc932417521ca24f2b0459fe7e6e0b"
 416            "090339ec0aa6faefd5ccc2c6f4ce8e94"
 417            "1e36b26bd1ebc670d1bd1d665620abf7"
 418            "4f78a7f6d29809585a97daec58c6b050",
 419    },
 420    {
 421        /* NIST F.5.5 CTR-AES256.Encrypt */
 422        .path = "/crypto/cipher/aes-ctr-256",
 423        .alg = QCRYPTO_CIPHER_ALG_AES_256,
 424        .mode = QCRYPTO_CIPHER_MODE_CTR,
 425        .key = "603deb1015ca71be2b73aef0857d7781"
 426               "1f352c073b6108d72d9810a30914dff4",
 427        .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
 428        .plaintext  =
 429            "6bc1bee22e409f96e93d7e117393172a"
 430            "ae2d8a571e03ac9c9eb76fac45af8e51"
 431            "30c81c46a35ce411e5fbc1191a0a52ef"
 432            "f69f2445df4f9b17ad2b417be66c3710",
 433        .ciphertext =
 434            "601ec313775789a5b7a7f504bbf3d228"
 435            "f443e3ca4d62b59aca84e990cacaf5c5"
 436            "2b0930daa23de94ce87017ba2d84988d"
 437            "dfc9c58db67aada613c2dd08457941a6",
 438    }
 439};
 440
 441
 442static inline int unhex(char c)
 443{
 444    if (c >= 'a' && c <= 'f') {
 445        return 10 + (c - 'a');
 446    }
 447    if (c >= 'A' && c <= 'F') {
 448        return 10 + (c - 'A');
 449    }
 450    return c - '0';
 451}
 452
 453static inline char hex(int i)
 454{
 455    if (i < 10) {
 456        return '0' + i;
 457    }
 458    return 'a' + (i - 10);
 459}
 460
 461static size_t unhex_string(const char *hexstr,
 462                           uint8_t **data)
 463{
 464    size_t len;
 465    size_t i;
 466
 467    if (!hexstr) {
 468        *data = NULL;
 469        return 0;
 470    }
 471
 472    len = strlen(hexstr);
 473    *data = g_new0(uint8_t, len / 2);
 474
 475    for (i = 0; i < len; i += 2) {
 476        (*data)[i/2] = (unhex(hexstr[i]) << 4) | unhex(hexstr[i+1]);
 477    }
 478    return len / 2;
 479}
 480
 481static char *hex_string(const uint8_t *bytes,
 482                        size_t len)
 483{
 484    char *hexstr = g_new0(char, len * 2 + 1);
 485    size_t i;
 486
 487    for (i = 0; i < len; i++) {
 488        hexstr[i*2] = hex((bytes[i] >> 4) & 0xf);
 489        hexstr[i*2+1] = hex(bytes[i] & 0xf);
 490    }
 491    hexstr[len*2] = '\0';
 492
 493    return hexstr;
 494}
 495
 496static void test_cipher(const void *opaque)
 497{
 498    const QCryptoCipherTestData *data = opaque;
 499
 500    QCryptoCipher *cipher;
 501    uint8_t *key, *iv = NULL, *ciphertext = NULL,
 502        *plaintext = NULL, *outtext = NULL;
 503    size_t nkey, niv = 0, nciphertext = 0, nplaintext = 0;
 504    char *outtexthex = NULL;
 505    size_t ivsize, keysize, blocksize;
 506    Error *err = NULL;
 507
 508    nkey = unhex_string(data->key, &key);
 509    if (data->iv) {
 510        niv = unhex_string(data->iv, &iv);
 511    }
 512    if (data->ciphertext) {
 513        nciphertext = unhex_string(data->ciphertext, &ciphertext);
 514    }
 515    if (data->plaintext) {
 516        nplaintext = unhex_string(data->plaintext, &plaintext);
 517    }
 518
 519    g_assert(nciphertext == nplaintext);
 520
 521    outtext = g_new0(uint8_t, nciphertext);
 522
 523    cipher = qcrypto_cipher_new(
 524        data->alg, data->mode,
 525        key, nkey,
 526        &err);
 527    if (data->plaintext) {
 528        g_assert(err == NULL);
 529        g_assert(cipher != NULL);
 530    } else {
 531        error_free_or_abort(&err);
 532        g_assert(cipher == NULL);
 533        goto cleanup;
 534    }
 535
 536    keysize = qcrypto_cipher_get_key_len(data->alg);
 537    blocksize = qcrypto_cipher_get_block_len(data->alg);
 538    ivsize = qcrypto_cipher_get_iv_len(data->alg, data->mode);
 539
 540    if (data->mode == QCRYPTO_CIPHER_MODE_XTS) {
 541        g_assert_cmpint(keysize * 2, ==, nkey);
 542    } else {
 543        g_assert_cmpint(keysize, ==, nkey);
 544    }
 545    g_assert_cmpint(ivsize, ==, niv);
 546    if (niv) {
 547        g_assert_cmpint(blocksize, ==, niv);
 548    }
 549
 550    if (iv) {
 551        g_assert(qcrypto_cipher_setiv(cipher,
 552                                      iv, niv,
 553                                      &error_abort) == 0);
 554    }
 555    g_assert(qcrypto_cipher_encrypt(cipher,
 556                                    plaintext,
 557                                    outtext,
 558                                    nplaintext,
 559                                    &error_abort) == 0);
 560
 561    outtexthex = hex_string(outtext, nciphertext);
 562
 563    g_assert_cmpstr(outtexthex, ==, data->ciphertext);
 564
 565    g_free(outtexthex);
 566
 567    if (iv) {
 568        g_assert(qcrypto_cipher_setiv(cipher,
 569                                      iv, niv,
 570                                      &error_abort) == 0);
 571    }
 572    g_assert(qcrypto_cipher_decrypt(cipher,
 573                                    ciphertext,
 574                                    outtext,
 575                                    nplaintext,
 576                                    &error_abort) == 0);
 577
 578    outtexthex = hex_string(outtext, nplaintext);
 579
 580    g_assert_cmpstr(outtexthex, ==, data->plaintext);
 581
 582 cleanup:
 583    g_free(outtext);
 584    g_free(outtexthex);
 585    g_free(key);
 586    g_free(iv);
 587    g_free(ciphertext);
 588    g_free(plaintext);
 589    qcrypto_cipher_free(cipher);
 590}
 591
 592
 593static void test_cipher_null_iv(void)
 594{
 595    QCryptoCipher *cipher;
 596    uint8_t key[32] = { 0 };
 597    uint8_t plaintext[32] = { 0 };
 598    uint8_t ciphertext[32] = { 0 };
 599
 600    cipher = qcrypto_cipher_new(
 601        QCRYPTO_CIPHER_ALG_AES_256,
 602        QCRYPTO_CIPHER_MODE_CBC,
 603        key, sizeof(key),
 604        &error_abort);
 605    g_assert(cipher != NULL);
 606
 607    /* Don't call qcrypto_cipher_setiv */
 608
 609    qcrypto_cipher_encrypt(cipher,
 610                           plaintext,
 611                           ciphertext,
 612                           sizeof(plaintext),
 613                           &error_abort);
 614
 615    qcrypto_cipher_free(cipher);
 616}
 617
 618static void test_cipher_short_plaintext(void)
 619{
 620    Error *err = NULL;
 621    QCryptoCipher *cipher;
 622    uint8_t key[32] = { 0 };
 623    uint8_t plaintext1[20] = { 0 };
 624    uint8_t ciphertext1[20] = { 0 };
 625    uint8_t plaintext2[40] = { 0 };
 626    uint8_t ciphertext2[40] = { 0 };
 627    int ret;
 628
 629    cipher = qcrypto_cipher_new(
 630        QCRYPTO_CIPHER_ALG_AES_256,
 631        QCRYPTO_CIPHER_MODE_CBC,
 632        key, sizeof(key),
 633        &error_abort);
 634    g_assert(cipher != NULL);
 635
 636    /* Should report an error as plaintext is shorter
 637     * than block size
 638     */
 639    ret = qcrypto_cipher_encrypt(cipher,
 640                                 plaintext1,
 641                                 ciphertext1,
 642                                 sizeof(plaintext1),
 643                                 &err);
 644    g_assert(ret == -1);
 645    g_assert(err != NULL);
 646
 647    error_free(err);
 648    err = NULL;
 649
 650    /* Should report an error as plaintext is larger than
 651     * block size, but not a multiple of block size
 652     */
 653    ret = qcrypto_cipher_encrypt(cipher,
 654                                 plaintext2,
 655                                 ciphertext2,
 656                                 sizeof(plaintext2),
 657                                 &err);
 658    g_assert(ret == -1);
 659    g_assert(err != NULL);
 660
 661    error_free(err);
 662    qcrypto_cipher_free(cipher);
 663}
 664
 665int main(int argc, char **argv)
 666{
 667    size_t i;
 668
 669    g_test_init(&argc, &argv, NULL);
 670
 671    g_assert(qcrypto_init(NULL) == 0);
 672
 673    for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
 674        if (qcrypto_cipher_supports(test_data[i].alg, test_data[i].mode)) {
 675            g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher);
 676        }
 677    }
 678
 679    g_test_add_func("/crypto/cipher/null-iv",
 680                    test_cipher_null_iv);
 681
 682    g_test_add_func("/crypto/cipher/short-plaintext",
 683                    test_cipher_short_plaintext);
 684
 685    return g_test_run();
 686}
 687