1238384Sjkim/* ==================================================================== 2238384Sjkim * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 3238384Sjkim * 4238384Sjkim * Rights for redistribution and usage in source and binary 5238384Sjkim * forms are granted according to the OpenSSL license. 6238384Sjkim */ 7238384Sjkim 8238384Sjkim#include <openssl/crypto.h> 9238384Sjkim#include "modes_lcl.h" 10238384Sjkim#include <string.h> 11238384Sjkim 12238384Sjkim#ifndef MODES_DEBUG 13238384Sjkim# ifndef NDEBUG 14238384Sjkim# define NDEBUG 15238384Sjkim# endif 16238384Sjkim#endif 17238384Sjkim#include <assert.h> 18238384Sjkim 19238384Sjkim/* 20238384Sjkim * Trouble with Ciphertext Stealing, CTS, mode is that there is no 21238384Sjkim * common official specification, but couple of cipher/application 22238384Sjkim * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to 23238384Sjkim * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which 24238384Sjkim * deviates from mentioned RFCs. Most notably it allows input to be 25238384Sjkim * of block length and it doesn't flip the order of the last two 26238384Sjkim * blocks. CTS is being discussed even in ECB context, but it's not 27238384Sjkim * adopted for any known application. This implementation provides 28238384Sjkim * two interfaces: one compliant with above mentioned RFCs and one 29238384Sjkim * compliant with the NIST proposal, both extending CBC mode. 30238384Sjkim */ 31238384Sjkim 32296341Sdelphijsize_t CRYPTO_cts128_encrypt_block(const unsigned char *in, 33296341Sdelphij unsigned char *out, size_t len, 34296341Sdelphij const void *key, unsigned char ivec[16], 35296341Sdelphij block128_f block) 36296341Sdelphij{ 37296341Sdelphij size_t residue, n; 38238384Sjkim 39296341Sdelphij assert(in && out && key && ivec); 40238384Sjkim 41296341Sdelphij if (len <= 16) 42296341Sdelphij return 0; 43238384Sjkim 44296341Sdelphij if ((residue = len % 16) == 0) 45296341Sdelphij residue = 16; 46238384Sjkim 47296341Sdelphij len -= residue; 48238384Sjkim 49296341Sdelphij CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block); 50238384Sjkim 51296341Sdelphij in += len; 52296341Sdelphij out += len; 53238384Sjkim 54296341Sdelphij for (n = 0; n < residue; ++n) 55296341Sdelphij ivec[n] ^= in[n]; 56296341Sdelphij (*block) (ivec, ivec, key); 57296341Sdelphij memcpy(out, out - 16, residue); 58296341Sdelphij memcpy(out - 16, ivec, 16); 59238384Sjkim 60296341Sdelphij return len + residue; 61238384Sjkim} 62238384Sjkim 63296341Sdelphijsize_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, 64296341Sdelphij unsigned char *out, size_t len, 65296341Sdelphij const void *key, 66296341Sdelphij unsigned char ivec[16], 67296341Sdelphij block128_f block) 68296341Sdelphij{ 69296341Sdelphij size_t residue, n; 70238384Sjkim 71296341Sdelphij assert(in && out && key && ivec); 72238384Sjkim 73296341Sdelphij if (len < 16) 74296341Sdelphij return 0; 75238384Sjkim 76296341Sdelphij residue = len % 16; 77238384Sjkim 78296341Sdelphij len -= residue; 79238384Sjkim 80296341Sdelphij CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block); 81238384Sjkim 82296341Sdelphij if (residue == 0) 83296341Sdelphij return len; 84238384Sjkim 85296341Sdelphij in += len; 86296341Sdelphij out += len; 87238384Sjkim 88296341Sdelphij for (n = 0; n < residue; ++n) 89296341Sdelphij ivec[n] ^= in[n]; 90296341Sdelphij (*block) (ivec, ivec, key); 91296341Sdelphij memcpy(out - 16 + residue, ivec, 16); 92238384Sjkim 93296341Sdelphij return len + residue; 94238384Sjkim} 95238384Sjkim 96238384Sjkimsize_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out, 97296341Sdelphij size_t len, const void *key, 98296341Sdelphij unsigned char ivec[16], cbc128_f cbc) 99296341Sdelphij{ 100296341Sdelphij size_t residue; 101296341Sdelphij union { 102296341Sdelphij size_t align; 103296341Sdelphij unsigned char c[16]; 104296341Sdelphij } tmp; 105238384Sjkim 106296341Sdelphij assert(in && out && key && ivec); 107238384Sjkim 108296341Sdelphij if (len <= 16) 109296341Sdelphij return 0; 110238384Sjkim 111296341Sdelphij if ((residue = len % 16) == 0) 112296341Sdelphij residue = 16; 113238384Sjkim 114296341Sdelphij len -= residue; 115238384Sjkim 116296341Sdelphij (*cbc) (in, out, len, key, ivec, 1); 117238384Sjkim 118296341Sdelphij in += len; 119296341Sdelphij out += len; 120238384Sjkim 121238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 122296341Sdelphij memcpy(tmp.c, out - 16, 16); 123296341Sdelphij (*cbc) (in, out - 16, residue, key, ivec, 1); 124296341Sdelphij memcpy(out, tmp.c, residue); 125238384Sjkim#else 126296341Sdelphij memset(tmp.c, 0, sizeof(tmp)); 127296341Sdelphij memcpy(tmp.c, in, residue); 128296341Sdelphij memcpy(out, out - 16, residue); 129296341Sdelphij (*cbc) (tmp.c, out - 16, 16, key, ivec, 1); 130238384Sjkim#endif 131296341Sdelphij return len + residue; 132238384Sjkim} 133238384Sjkim 134238384Sjkimsize_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out, 135296341Sdelphij size_t len, const void *key, 136296341Sdelphij unsigned char ivec[16], cbc128_f cbc) 137296341Sdelphij{ 138296341Sdelphij size_t residue; 139296341Sdelphij union { 140296341Sdelphij size_t align; 141296341Sdelphij unsigned char c[16]; 142296341Sdelphij } tmp; 143238384Sjkim 144296341Sdelphij assert(in && out && key && ivec); 145238384Sjkim 146296341Sdelphij if (len < 16) 147296341Sdelphij return 0; 148238384Sjkim 149296341Sdelphij residue = len % 16; 150238384Sjkim 151296341Sdelphij len -= residue; 152238384Sjkim 153296341Sdelphij (*cbc) (in, out, len, key, ivec, 1); 154238384Sjkim 155296341Sdelphij if (residue == 0) 156296341Sdelphij return len; 157238384Sjkim 158296341Sdelphij in += len; 159296341Sdelphij out += len; 160238384Sjkim 161238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 162296341Sdelphij (*cbc) (in, out - 16 + residue, residue, key, ivec, 1); 163238384Sjkim#else 164296341Sdelphij memset(tmp.c, 0, sizeof(tmp)); 165296341Sdelphij memcpy(tmp.c, in, residue); 166296341Sdelphij (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1); 167238384Sjkim#endif 168296341Sdelphij return len + residue; 169238384Sjkim} 170238384Sjkim 171296341Sdelphijsize_t CRYPTO_cts128_decrypt_block(const unsigned char *in, 172296341Sdelphij unsigned char *out, size_t len, 173296341Sdelphij const void *key, unsigned char ivec[16], 174296341Sdelphij block128_f block) 175296341Sdelphij{ 176296341Sdelphij size_t residue, n; 177296341Sdelphij union { 178296341Sdelphij size_t align; 179296341Sdelphij unsigned char c[32]; 180296341Sdelphij } tmp; 181238384Sjkim 182296341Sdelphij assert(in && out && key && ivec); 183238384Sjkim 184296341Sdelphij if (len <= 16) 185296341Sdelphij return 0; 186238384Sjkim 187296341Sdelphij if ((residue = len % 16) == 0) 188296341Sdelphij residue = 16; 189238384Sjkim 190296341Sdelphij len -= 16 + residue; 191238384Sjkim 192296341Sdelphij if (len) { 193296341Sdelphij CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); 194296341Sdelphij in += len; 195296341Sdelphij out += len; 196296341Sdelphij } 197238384Sjkim 198296341Sdelphij (*block) (in, tmp.c + 16, key); 199238384Sjkim 200296341Sdelphij memcpy(tmp.c, tmp.c + 16, 16); 201296341Sdelphij memcpy(tmp.c, in + 16, residue); 202296341Sdelphij (*block) (tmp.c, tmp.c, key); 203238384Sjkim 204296341Sdelphij for (n = 0; n < 16; ++n) { 205296341Sdelphij unsigned char c = in[n]; 206296341Sdelphij out[n] = tmp.c[n] ^ ivec[n]; 207296341Sdelphij ivec[n] = c; 208296341Sdelphij } 209296341Sdelphij for (residue += 16; n < residue; ++n) 210296341Sdelphij out[n] = tmp.c[n] ^ in[n]; 211238384Sjkim 212296341Sdelphij return 16 + len + residue; 213238384Sjkim} 214238384Sjkim 215296341Sdelphijsize_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, 216296341Sdelphij unsigned char *out, size_t len, 217296341Sdelphij const void *key, 218296341Sdelphij unsigned char ivec[16], 219296341Sdelphij block128_f block) 220296341Sdelphij{ 221296341Sdelphij size_t residue, n; 222296341Sdelphij union { 223296341Sdelphij size_t align; 224296341Sdelphij unsigned char c[32]; 225296341Sdelphij } tmp; 226238384Sjkim 227296341Sdelphij assert(in && out && key && ivec); 228238384Sjkim 229296341Sdelphij if (len < 16) 230296341Sdelphij return 0; 231238384Sjkim 232296341Sdelphij residue = len % 16; 233238384Sjkim 234296341Sdelphij if (residue == 0) { 235296341Sdelphij CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); 236296341Sdelphij return len; 237296341Sdelphij } 238238384Sjkim 239296341Sdelphij len -= 16 + residue; 240238384Sjkim 241296341Sdelphij if (len) { 242296341Sdelphij CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); 243296341Sdelphij in += len; 244296341Sdelphij out += len; 245296341Sdelphij } 246238384Sjkim 247296341Sdelphij (*block) (in + residue, tmp.c + 16, key); 248238384Sjkim 249296341Sdelphij memcpy(tmp.c, tmp.c + 16, 16); 250296341Sdelphij memcpy(tmp.c, in, residue); 251296341Sdelphij (*block) (tmp.c, tmp.c, key); 252238384Sjkim 253296341Sdelphij for (n = 0; n < 16; ++n) { 254296341Sdelphij unsigned char c = in[n]; 255296341Sdelphij out[n] = tmp.c[n] ^ ivec[n]; 256296341Sdelphij ivec[n] = in[n + residue]; 257296341Sdelphij tmp.c[n] = c; 258296341Sdelphij } 259296341Sdelphij for (residue += 16; n < residue; ++n) 260296341Sdelphij out[n] = tmp.c[n] ^ tmp.c[n - 16]; 261238384Sjkim 262296341Sdelphij return 16 + len + residue; 263238384Sjkim} 264238384Sjkim 265238384Sjkimsize_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out, 266296341Sdelphij size_t len, const void *key, 267296341Sdelphij unsigned char ivec[16], cbc128_f cbc) 268296341Sdelphij{ 269296341Sdelphij size_t residue; 270296341Sdelphij union { 271296341Sdelphij size_t align; 272296341Sdelphij unsigned char c[32]; 273296341Sdelphij } tmp; 274238384Sjkim 275296341Sdelphij assert(in && out && key && ivec); 276238384Sjkim 277296341Sdelphij if (len <= 16) 278296341Sdelphij return 0; 279238384Sjkim 280296341Sdelphij if ((residue = len % 16) == 0) 281296341Sdelphij residue = 16; 282238384Sjkim 283296341Sdelphij len -= 16 + residue; 284238384Sjkim 285296341Sdelphij if (len) { 286296341Sdelphij (*cbc) (in, out, len, key, ivec, 0); 287296341Sdelphij in += len; 288296341Sdelphij out += len; 289296341Sdelphij } 290238384Sjkim 291296341Sdelphij memset(tmp.c, 0, sizeof(tmp)); 292296341Sdelphij /* 293296341Sdelphij * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] 294296341Sdelphij */ 295296341Sdelphij (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0); 296238384Sjkim 297296341Sdelphij memcpy(tmp.c, in + 16, residue); 298238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 299296341Sdelphij (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0); 300238384Sjkim#else 301296341Sdelphij (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0); 302296341Sdelphij memcpy(out, tmp.c, 16 + residue); 303238384Sjkim#endif 304296341Sdelphij return 16 + len + residue; 305238384Sjkim} 306238384Sjkim 307238384Sjkimsize_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out, 308296341Sdelphij size_t len, const void *key, 309296341Sdelphij unsigned char ivec[16], cbc128_f cbc) 310296341Sdelphij{ 311296341Sdelphij size_t residue; 312296341Sdelphij union { 313296341Sdelphij size_t align; 314296341Sdelphij unsigned char c[32]; 315296341Sdelphij } tmp; 316238384Sjkim 317296341Sdelphij assert(in && out && key && ivec); 318238384Sjkim 319296341Sdelphij if (len < 16) 320296341Sdelphij return 0; 321238384Sjkim 322296341Sdelphij residue = len % 16; 323238384Sjkim 324296341Sdelphij if (residue == 0) { 325296341Sdelphij (*cbc) (in, out, len, key, ivec, 0); 326296341Sdelphij return len; 327296341Sdelphij } 328238384Sjkim 329296341Sdelphij len -= 16 + residue; 330238384Sjkim 331296341Sdelphij if (len) { 332296341Sdelphij (*cbc) (in, out, len, key, ivec, 0); 333296341Sdelphij in += len; 334296341Sdelphij out += len; 335296341Sdelphij } 336238384Sjkim 337296341Sdelphij memset(tmp.c, 0, sizeof(tmp)); 338296341Sdelphij /* 339296341Sdelphij * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] 340296341Sdelphij */ 341296341Sdelphij (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0); 342238384Sjkim 343296341Sdelphij memcpy(tmp.c, in, residue); 344238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 345296341Sdelphij (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0); 346238384Sjkim#else 347296341Sdelphij (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0); 348296341Sdelphij memcpy(out, tmp.c, 16 + residue); 349238384Sjkim#endif 350296341Sdelphij return 16 + len + residue; 351238384Sjkim} 352238384Sjkim 353238384Sjkim#if defined(SELFTEST) 354296341Sdelphij# include <stdio.h> 355296341Sdelphij# include <openssl/aes.h> 356238384Sjkim 357238384Sjkim/* test vectors from RFC 3962 */ 358238384Sjkimstatic const unsigned char test_key[16] = "chicken teriyaki"; 359238384Sjkimstatic const unsigned char test_input[64] = 360296341Sdelphij "I would like the" " General Gau's C" 361296341Sdelphij "hicken, please, " "and wonton soup."; 362296341Sdelphijstatic const unsigned char test_iv[16] = 363296341Sdelphij { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 364238384Sjkim 365296341Sdelphijstatic const unsigned char vector_17[17] = { 366296341Sdelphij 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4, 367296341Sdelphij 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f, 368296341Sdelphij 0x97 369296341Sdelphij}; 370238384Sjkim 371296341Sdelphijstatic const unsigned char vector_31[31] = { 372296341Sdelphij 0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1, 373296341Sdelphij 0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22, 374296341Sdelphij 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 375296341Sdelphij 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5 376296341Sdelphij}; 377296341Sdelphij 378296341Sdelphijstatic const unsigned char vector_32[32] = { 379296341Sdelphij 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 380296341Sdelphij 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8, 381296341Sdelphij 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 382296341Sdelphij 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84 383296341Sdelphij}; 384296341Sdelphij 385296341Sdelphijstatic const unsigned char vector_47[47] = { 386296341Sdelphij 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 387296341Sdelphij 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, 388296341Sdelphij 0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c, 389296341Sdelphij 0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e, 390296341Sdelphij 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 391296341Sdelphij 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5 392296341Sdelphij}; 393296341Sdelphij 394296341Sdelphijstatic const unsigned char vector_48[48] = { 395296341Sdelphij 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 396296341Sdelphij 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, 397296341Sdelphij 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0, 398296341Sdelphij 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8, 399296341Sdelphij 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 400296341Sdelphij 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8 401296341Sdelphij}; 402296341Sdelphij 403296341Sdelphijstatic const unsigned char vector_64[64] = { 404296341Sdelphij 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 405296341Sdelphij 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, 406296341Sdelphij 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 407296341Sdelphij 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8, 408296341Sdelphij 0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5, 409296341Sdelphij 0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40, 410296341Sdelphij 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0, 411296341Sdelphij 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8 412296341Sdelphij}; 413296341Sdelphij 414238384Sjkimstatic AES_KEY encks, decks; 415238384Sjkim 416296341Sdelphijvoid test_vector(const unsigned char *vector, size_t len) 417296341Sdelphij{ 418296341Sdelphij unsigned char iv[sizeof(test_iv)]; 419296341Sdelphij unsigned char cleartext[64], ciphertext[64]; 420296341Sdelphij size_t tail; 421238384Sjkim 422296341Sdelphij printf("vector_%d\n", len); 423296341Sdelphij fflush(stdout); 424238384Sjkim 425296341Sdelphij if ((tail = len % 16) == 0) 426296341Sdelphij tail = 16; 427296341Sdelphij tail += 16; 428238384Sjkim 429296341Sdelphij /* test block-based encryption */ 430296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 431296341Sdelphij CRYPTO_cts128_encrypt_block(test_input, ciphertext, len, &encks, iv, 432296341Sdelphij (block128_f) AES_encrypt); 433296341Sdelphij if (memcmp(ciphertext, vector, len)) 434296341Sdelphij fprintf(stderr, "output_%d mismatch\n", len), exit(1); 435296341Sdelphij if (memcmp(iv, vector + len - tail, sizeof(iv))) 436296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(1); 437238384Sjkim 438296341Sdelphij /* test block-based decryption */ 439296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 440296341Sdelphij CRYPTO_cts128_decrypt_block(ciphertext, cleartext, len, &decks, iv, 441296341Sdelphij (block128_f) AES_decrypt); 442296341Sdelphij if (memcmp(cleartext, test_input, len)) 443296341Sdelphij fprintf(stderr, "input_%d mismatch\n", len), exit(2); 444296341Sdelphij if (memcmp(iv, vector + len - tail, sizeof(iv))) 445296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(2); 446238384Sjkim 447296341Sdelphij /* test streamed encryption */ 448296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 449296341Sdelphij CRYPTO_cts128_encrypt(test_input, ciphertext, len, &encks, iv, 450296341Sdelphij (cbc128_f) AES_cbc_encrypt); 451296341Sdelphij if (memcmp(ciphertext, vector, len)) 452296341Sdelphij fprintf(stderr, "output_%d mismatch\n", len), exit(3); 453296341Sdelphij if (memcmp(iv, vector + len - tail, sizeof(iv))) 454296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(3); 455238384Sjkim 456296341Sdelphij /* test streamed decryption */ 457296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 458296341Sdelphij CRYPTO_cts128_decrypt(ciphertext, cleartext, len, &decks, iv, 459296341Sdelphij (cbc128_f) AES_cbc_encrypt); 460296341Sdelphij if (memcmp(cleartext, test_input, len)) 461296341Sdelphij fprintf(stderr, "input_%d mismatch\n", len), exit(4); 462296341Sdelphij if (memcmp(iv, vector + len - tail, sizeof(iv))) 463296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(4); 464238384Sjkim} 465238384Sjkim 466296341Sdelphijvoid test_nistvector(const unsigned char *vector, size_t len) 467296341Sdelphij{ 468296341Sdelphij unsigned char iv[sizeof(test_iv)]; 469296341Sdelphij unsigned char cleartext[64], ciphertext[64], nistvector[64]; 470296341Sdelphij size_t tail; 471238384Sjkim 472296341Sdelphij printf("nistvector_%d\n", len); 473296341Sdelphij fflush(stdout); 474238384Sjkim 475296341Sdelphij if ((tail = len % 16) == 0) 476296341Sdelphij tail = 16; 477238384Sjkim 478296341Sdelphij len -= 16 + tail; 479296341Sdelphij memcpy(nistvector, vector, len); 480296341Sdelphij /* flip two last blocks */ 481296341Sdelphij memcpy(nistvector + len, vector + len + 16, tail); 482296341Sdelphij memcpy(nistvector + len + tail, vector + len, 16); 483296341Sdelphij len += 16 + tail; 484296341Sdelphij tail = 16; 485238384Sjkim 486296341Sdelphij /* test block-based encryption */ 487296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 488296341Sdelphij CRYPTO_nistcts128_encrypt_block(test_input, ciphertext, len, &encks, iv, 489296341Sdelphij (block128_f) AES_encrypt); 490296341Sdelphij if (memcmp(ciphertext, nistvector, len)) 491296341Sdelphij fprintf(stderr, "output_%d mismatch\n", len), exit(1); 492296341Sdelphij if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 493296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(1); 494238384Sjkim 495296341Sdelphij /* test block-based decryption */ 496296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 497296341Sdelphij CRYPTO_nistcts128_decrypt_block(ciphertext, cleartext, len, &decks, iv, 498296341Sdelphij (block128_f) AES_decrypt); 499296341Sdelphij if (memcmp(cleartext, test_input, len)) 500296341Sdelphij fprintf(stderr, "input_%d mismatch\n", len), exit(2); 501296341Sdelphij if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 502296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(2); 503238384Sjkim 504296341Sdelphij /* test streamed encryption */ 505296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 506296341Sdelphij CRYPTO_nistcts128_encrypt(test_input, ciphertext, len, &encks, iv, 507296341Sdelphij (cbc128_f) AES_cbc_encrypt); 508296341Sdelphij if (memcmp(ciphertext, nistvector, len)) 509296341Sdelphij fprintf(stderr, "output_%d mismatch\n", len), exit(3); 510296341Sdelphij if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 511296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(3); 512238384Sjkim 513296341Sdelphij /* test streamed decryption */ 514296341Sdelphij memcpy(iv, test_iv, sizeof(test_iv)); 515296341Sdelphij CRYPTO_nistcts128_decrypt(ciphertext, cleartext, len, &decks, iv, 516296341Sdelphij (cbc128_f) AES_cbc_encrypt); 517296341Sdelphij if (memcmp(cleartext, test_input, len)) 518296341Sdelphij fprintf(stderr, "input_%d mismatch\n", len), exit(4); 519296341Sdelphij if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 520296341Sdelphij fprintf(stderr, "iv_%d mismatch\n", len), exit(4); 521238384Sjkim} 522238384Sjkim 523238384Sjkimint main() 524238384Sjkim{ 525296341Sdelphij AES_set_encrypt_key(test_key, 128, &encks); 526296341Sdelphij AES_set_decrypt_key(test_key, 128, &decks); 527238384Sjkim 528296341Sdelphij test_vector(vector_17, sizeof(vector_17)); 529296341Sdelphij test_vector(vector_31, sizeof(vector_31)); 530296341Sdelphij test_vector(vector_32, sizeof(vector_32)); 531296341Sdelphij test_vector(vector_47, sizeof(vector_47)); 532296341Sdelphij test_vector(vector_48, sizeof(vector_48)); 533296341Sdelphij test_vector(vector_64, sizeof(vector_64)); 534238384Sjkim 535296341Sdelphij test_nistvector(vector_17, sizeof(vector_17)); 536296341Sdelphij test_nistvector(vector_31, sizeof(vector_31)); 537296341Sdelphij test_nistvector(vector_32, sizeof(vector_32)); 538296341Sdelphij test_nistvector(vector_47, sizeof(vector_47)); 539296341Sdelphij test_nistvector(vector_48, sizeof(vector_48)); 540296341Sdelphij test_nistvector(vector_64, sizeof(vector_64)); 541238384Sjkim 542296341Sdelphij return 0; 543238384Sjkim} 544238384Sjkim#endif 545