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 32280304Sjkimsize_t CRYPTO_cts128_encrypt_block(const unsigned char *in, 33280304Sjkim unsigned char *out, size_t len, 34280304Sjkim const void *key, unsigned char ivec[16], 35280304Sjkim block128_f block) 36280304Sjkim{ 37280304Sjkim size_t residue, n; 38238384Sjkim 39280304Sjkim assert(in && out && key && ivec); 40238384Sjkim 41280304Sjkim if (len <= 16) 42280304Sjkim return 0; 43238384Sjkim 44280304Sjkim if ((residue = len % 16) == 0) 45280304Sjkim residue = 16; 46238384Sjkim 47280304Sjkim len -= residue; 48238384Sjkim 49280304Sjkim CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block); 50238384Sjkim 51280304Sjkim in += len; 52280304Sjkim out += len; 53238384Sjkim 54280304Sjkim for (n = 0; n < residue; ++n) 55280304Sjkim ivec[n] ^= in[n]; 56280304Sjkim (*block) (ivec, ivec, key); 57280304Sjkim memcpy(out, out - 16, residue); 58280304Sjkim memcpy(out - 16, ivec, 16); 59238384Sjkim 60280304Sjkim return len + residue; 61238384Sjkim} 62238384Sjkim 63280304Sjkimsize_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, 64280304Sjkim unsigned char *out, size_t len, 65280304Sjkim const void *key, 66280304Sjkim unsigned char ivec[16], 67280304Sjkim block128_f block) 68280304Sjkim{ 69280304Sjkim size_t residue, n; 70238384Sjkim 71280304Sjkim assert(in && out && key && ivec); 72238384Sjkim 73280304Sjkim if (len < 16) 74280304Sjkim return 0; 75238384Sjkim 76280304Sjkim residue = len % 16; 77238384Sjkim 78280304Sjkim len -= residue; 79238384Sjkim 80280304Sjkim CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block); 81238384Sjkim 82280304Sjkim if (residue == 0) 83280304Sjkim return len; 84238384Sjkim 85280304Sjkim in += len; 86280304Sjkim out += len; 87238384Sjkim 88280304Sjkim for (n = 0; n < residue; ++n) 89280304Sjkim ivec[n] ^= in[n]; 90280304Sjkim (*block) (ivec, ivec, key); 91280304Sjkim memcpy(out - 16 + residue, ivec, 16); 92238384Sjkim 93280304Sjkim return len + residue; 94238384Sjkim} 95238384Sjkim 96238384Sjkimsize_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out, 97280304Sjkim size_t len, const void *key, 98280304Sjkim unsigned char ivec[16], cbc128_f cbc) 99280304Sjkim{ 100280304Sjkim size_t residue; 101280304Sjkim union { 102280304Sjkim size_t align; 103280304Sjkim unsigned char c[16]; 104280304Sjkim } tmp; 105238384Sjkim 106280304Sjkim assert(in && out && key && ivec); 107238384Sjkim 108280304Sjkim if (len <= 16) 109280304Sjkim return 0; 110238384Sjkim 111280304Sjkim if ((residue = len % 16) == 0) 112280304Sjkim residue = 16; 113238384Sjkim 114280304Sjkim len -= residue; 115238384Sjkim 116280304Sjkim (*cbc) (in, out, len, key, ivec, 1); 117238384Sjkim 118280304Sjkim in += len; 119280304Sjkim out += len; 120238384Sjkim 121238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 122280304Sjkim memcpy(tmp.c, out - 16, 16); 123280304Sjkim (*cbc) (in, out - 16, residue, key, ivec, 1); 124280304Sjkim memcpy(out, tmp.c, residue); 125238384Sjkim#else 126280304Sjkim memset(tmp.c, 0, sizeof(tmp)); 127280304Sjkim memcpy(tmp.c, in, residue); 128280304Sjkim memcpy(out, out - 16, residue); 129280304Sjkim (*cbc) (tmp.c, out - 16, 16, key, ivec, 1); 130238384Sjkim#endif 131280304Sjkim return len + residue; 132238384Sjkim} 133238384Sjkim 134238384Sjkimsize_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out, 135280304Sjkim size_t len, const void *key, 136280304Sjkim unsigned char ivec[16], cbc128_f cbc) 137280304Sjkim{ 138280304Sjkim size_t residue; 139280304Sjkim union { 140280304Sjkim size_t align; 141280304Sjkim unsigned char c[16]; 142280304Sjkim } tmp; 143238384Sjkim 144280304Sjkim assert(in && out && key && ivec); 145238384Sjkim 146280304Sjkim if (len < 16) 147280304Sjkim return 0; 148238384Sjkim 149280304Sjkim residue = len % 16; 150238384Sjkim 151280304Sjkim len -= residue; 152238384Sjkim 153280304Sjkim (*cbc) (in, out, len, key, ivec, 1); 154238384Sjkim 155280304Sjkim if (residue == 0) 156280304Sjkim return len; 157238384Sjkim 158280304Sjkim in += len; 159280304Sjkim out += len; 160238384Sjkim 161238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 162280304Sjkim (*cbc) (in, out - 16 + residue, residue, key, ivec, 1); 163238384Sjkim#else 164280304Sjkim memset(tmp.c, 0, sizeof(tmp)); 165280304Sjkim memcpy(tmp.c, in, residue); 166280304Sjkim (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1); 167238384Sjkim#endif 168280304Sjkim return len + residue; 169238384Sjkim} 170238384Sjkim 171280304Sjkimsize_t CRYPTO_cts128_decrypt_block(const unsigned char *in, 172280304Sjkim unsigned char *out, size_t len, 173280304Sjkim const void *key, unsigned char ivec[16], 174280304Sjkim block128_f block) 175280304Sjkim{ 176280304Sjkim size_t residue, n; 177280304Sjkim union { 178280304Sjkim size_t align; 179280304Sjkim unsigned char c[32]; 180280304Sjkim } tmp; 181238384Sjkim 182280304Sjkim assert(in && out && key && ivec); 183238384Sjkim 184280304Sjkim if (len <= 16) 185280304Sjkim return 0; 186238384Sjkim 187280304Sjkim if ((residue = len % 16) == 0) 188280304Sjkim residue = 16; 189238384Sjkim 190280304Sjkim len -= 16 + residue; 191238384Sjkim 192280304Sjkim if (len) { 193280304Sjkim CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); 194280304Sjkim in += len; 195280304Sjkim out += len; 196280304Sjkim } 197238384Sjkim 198280304Sjkim (*block) (in, tmp.c + 16, key); 199238384Sjkim 200280304Sjkim memcpy(tmp.c, tmp.c + 16, 16); 201280304Sjkim memcpy(tmp.c, in + 16, residue); 202280304Sjkim (*block) (tmp.c, tmp.c, key); 203238384Sjkim 204280304Sjkim for (n = 0; n < 16; ++n) { 205280304Sjkim unsigned char c = in[n]; 206280304Sjkim out[n] = tmp.c[n] ^ ivec[n]; 207280304Sjkim ivec[n] = c; 208280304Sjkim } 209280304Sjkim for (residue += 16; n < residue; ++n) 210280304Sjkim out[n] = tmp.c[n] ^ in[n]; 211238384Sjkim 212280304Sjkim return 16 + len + residue; 213238384Sjkim} 214238384Sjkim 215280304Sjkimsize_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, 216280304Sjkim unsigned char *out, size_t len, 217280304Sjkim const void *key, 218280304Sjkim unsigned char ivec[16], 219280304Sjkim block128_f block) 220280304Sjkim{ 221280304Sjkim size_t residue, n; 222280304Sjkim union { 223280304Sjkim size_t align; 224280304Sjkim unsigned char c[32]; 225280304Sjkim } tmp; 226238384Sjkim 227280304Sjkim assert(in && out && key && ivec); 228238384Sjkim 229280304Sjkim if (len < 16) 230280304Sjkim return 0; 231238384Sjkim 232280304Sjkim residue = len % 16; 233238384Sjkim 234280304Sjkim if (residue == 0) { 235280304Sjkim CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); 236280304Sjkim return len; 237280304Sjkim } 238238384Sjkim 239280304Sjkim len -= 16 + residue; 240238384Sjkim 241280304Sjkim if (len) { 242280304Sjkim CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block); 243280304Sjkim in += len; 244280304Sjkim out += len; 245280304Sjkim } 246238384Sjkim 247280304Sjkim (*block) (in + residue, tmp.c + 16, key); 248238384Sjkim 249280304Sjkim memcpy(tmp.c, tmp.c + 16, 16); 250280304Sjkim memcpy(tmp.c, in, residue); 251280304Sjkim (*block) (tmp.c, tmp.c, key); 252238384Sjkim 253280304Sjkim for (n = 0; n < 16; ++n) { 254280304Sjkim unsigned char c = in[n]; 255280304Sjkim out[n] = tmp.c[n] ^ ivec[n]; 256280304Sjkim ivec[n] = in[n + residue]; 257280304Sjkim tmp.c[n] = c; 258280304Sjkim } 259280304Sjkim for (residue += 16; n < residue; ++n) 260280304Sjkim out[n] = tmp.c[n] ^ tmp.c[n - 16]; 261238384Sjkim 262280304Sjkim return 16 + len + residue; 263238384Sjkim} 264238384Sjkim 265238384Sjkimsize_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out, 266280304Sjkim size_t len, const void *key, 267280304Sjkim unsigned char ivec[16], cbc128_f cbc) 268280304Sjkim{ 269280304Sjkim size_t residue; 270280304Sjkim union { 271280304Sjkim size_t align; 272280304Sjkim unsigned char c[32]; 273280304Sjkim } tmp; 274238384Sjkim 275280304Sjkim assert(in && out && key && ivec); 276238384Sjkim 277280304Sjkim if (len <= 16) 278280304Sjkim return 0; 279238384Sjkim 280280304Sjkim if ((residue = len % 16) == 0) 281280304Sjkim residue = 16; 282238384Sjkim 283280304Sjkim len -= 16 + residue; 284238384Sjkim 285280304Sjkim if (len) { 286280304Sjkim (*cbc) (in, out, len, key, ivec, 0); 287280304Sjkim in += len; 288280304Sjkim out += len; 289280304Sjkim } 290238384Sjkim 291280304Sjkim memset(tmp.c, 0, sizeof(tmp)); 292280304Sjkim /* 293280304Sjkim * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] 294280304Sjkim */ 295280304Sjkim (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0); 296238384Sjkim 297280304Sjkim memcpy(tmp.c, in + 16, residue); 298238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 299280304Sjkim (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0); 300238384Sjkim#else 301280304Sjkim (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0); 302280304Sjkim memcpy(out, tmp.c, 16 + residue); 303238384Sjkim#endif 304280304Sjkim return 16 + len + residue; 305238384Sjkim} 306238384Sjkim 307238384Sjkimsize_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out, 308280304Sjkim size_t len, const void *key, 309280304Sjkim unsigned char ivec[16], cbc128_f cbc) 310280304Sjkim{ 311280304Sjkim size_t residue; 312280304Sjkim union { 313280304Sjkim size_t align; 314280304Sjkim unsigned char c[32]; 315280304Sjkim } tmp; 316238384Sjkim 317280304Sjkim assert(in && out && key && ivec); 318238384Sjkim 319280304Sjkim if (len < 16) 320280304Sjkim return 0; 321238384Sjkim 322280304Sjkim residue = len % 16; 323238384Sjkim 324280304Sjkim if (residue == 0) { 325280304Sjkim (*cbc) (in, out, len, key, ivec, 0); 326280304Sjkim return len; 327280304Sjkim } 328238384Sjkim 329280304Sjkim len -= 16 + residue; 330238384Sjkim 331280304Sjkim if (len) { 332280304Sjkim (*cbc) (in, out, len, key, ivec, 0); 333280304Sjkim in += len; 334280304Sjkim out += len; 335280304Sjkim } 336238384Sjkim 337280304Sjkim memset(tmp.c, 0, sizeof(tmp)); 338280304Sjkim /* 339280304Sjkim * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] 340280304Sjkim */ 341280304Sjkim (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0); 342238384Sjkim 343280304Sjkim memcpy(tmp.c, in, residue); 344238384Sjkim#if defined(CBC_HANDLES_TRUNCATED_IO) 345280304Sjkim (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0); 346238384Sjkim#else 347280304Sjkim (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0); 348280304Sjkim memcpy(out, tmp.c, 16 + residue); 349238384Sjkim#endif 350280304Sjkim return 16 + len + residue; 351238384Sjkim} 352238384Sjkim 353238384Sjkim#if defined(SELFTEST) 354280304Sjkim# include <stdio.h> 355280304Sjkim# 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] = 360280304Sjkim "I would like the" " General Gau's C" 361280304Sjkim "hicken, please, " "and wonton soup."; 362280304Sjkimstatic const unsigned char test_iv[16] = 363280304Sjkim { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 364238384Sjkim 365280304Sjkimstatic const unsigned char vector_17[17] = { 366280304Sjkim 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4, 367280304Sjkim 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f, 368280304Sjkim 0x97 369280304Sjkim}; 370238384Sjkim 371280304Sjkimstatic const unsigned char vector_31[31] = { 372280304Sjkim 0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1, 373280304Sjkim 0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22, 374280304Sjkim 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 375280304Sjkim 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5 376280304Sjkim}; 377280304Sjkim 378280304Sjkimstatic const unsigned char vector_32[32] = { 379280304Sjkim 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 380280304Sjkim 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8, 381280304Sjkim 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 382280304Sjkim 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84 383280304Sjkim}; 384280304Sjkim 385280304Sjkimstatic const unsigned char vector_47[47] = { 386280304Sjkim 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 387280304Sjkim 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, 388280304Sjkim 0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c, 389280304Sjkim 0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e, 390280304Sjkim 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 391280304Sjkim 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5 392280304Sjkim}; 393280304Sjkim 394280304Sjkimstatic const unsigned char vector_48[48] = { 395280304Sjkim 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 396280304Sjkim 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, 397280304Sjkim 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0, 398280304Sjkim 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8, 399280304Sjkim 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 400280304Sjkim 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8 401280304Sjkim}; 402280304Sjkim 403280304Sjkimstatic const unsigned char vector_64[64] = { 404280304Sjkim 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, 405280304Sjkim 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, 406280304Sjkim 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, 407280304Sjkim 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8, 408280304Sjkim 0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5, 409280304Sjkim 0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40, 410280304Sjkim 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0, 411280304Sjkim 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8 412280304Sjkim}; 413280304Sjkim 414238384Sjkimstatic AES_KEY encks, decks; 415238384Sjkim 416280304Sjkimvoid test_vector(const unsigned char *vector, size_t len) 417280304Sjkim{ 418280304Sjkim unsigned char iv[sizeof(test_iv)]; 419280304Sjkim unsigned char cleartext[64], ciphertext[64]; 420280304Sjkim size_t tail; 421238384Sjkim 422280304Sjkim printf("vector_%d\n", len); 423280304Sjkim fflush(stdout); 424238384Sjkim 425280304Sjkim if ((tail = len % 16) == 0) 426280304Sjkim tail = 16; 427280304Sjkim tail += 16; 428238384Sjkim 429280304Sjkim /* test block-based encryption */ 430280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 431280304Sjkim CRYPTO_cts128_encrypt_block(test_input, ciphertext, len, &encks, iv, 432280304Sjkim (block128_f) AES_encrypt); 433280304Sjkim if (memcmp(ciphertext, vector, len)) 434280304Sjkim fprintf(stderr, "output_%d mismatch\n", len), exit(1); 435280304Sjkim if (memcmp(iv, vector + len - tail, sizeof(iv))) 436280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(1); 437238384Sjkim 438280304Sjkim /* test block-based decryption */ 439280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 440280304Sjkim CRYPTO_cts128_decrypt_block(ciphertext, cleartext, len, &decks, iv, 441280304Sjkim (block128_f) AES_decrypt); 442280304Sjkim if (memcmp(cleartext, test_input, len)) 443280304Sjkim fprintf(stderr, "input_%d mismatch\n", len), exit(2); 444280304Sjkim if (memcmp(iv, vector + len - tail, sizeof(iv))) 445280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(2); 446238384Sjkim 447280304Sjkim /* test streamed encryption */ 448280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 449280304Sjkim CRYPTO_cts128_encrypt(test_input, ciphertext, len, &encks, iv, 450280304Sjkim (cbc128_f) AES_cbc_encrypt); 451280304Sjkim if (memcmp(ciphertext, vector, len)) 452280304Sjkim fprintf(stderr, "output_%d mismatch\n", len), exit(3); 453280304Sjkim if (memcmp(iv, vector + len - tail, sizeof(iv))) 454280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(3); 455238384Sjkim 456280304Sjkim /* test streamed decryption */ 457280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 458280304Sjkim CRYPTO_cts128_decrypt(ciphertext, cleartext, len, &decks, iv, 459280304Sjkim (cbc128_f) AES_cbc_encrypt); 460280304Sjkim if (memcmp(cleartext, test_input, len)) 461280304Sjkim fprintf(stderr, "input_%d mismatch\n", len), exit(4); 462280304Sjkim if (memcmp(iv, vector + len - tail, sizeof(iv))) 463280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(4); 464238384Sjkim} 465238384Sjkim 466280304Sjkimvoid test_nistvector(const unsigned char *vector, size_t len) 467280304Sjkim{ 468280304Sjkim unsigned char iv[sizeof(test_iv)]; 469280304Sjkim unsigned char cleartext[64], ciphertext[64], nistvector[64]; 470280304Sjkim size_t tail; 471238384Sjkim 472280304Sjkim printf("nistvector_%d\n", len); 473280304Sjkim fflush(stdout); 474238384Sjkim 475280304Sjkim if ((tail = len % 16) == 0) 476280304Sjkim tail = 16; 477238384Sjkim 478280304Sjkim len -= 16 + tail; 479280304Sjkim memcpy(nistvector, vector, len); 480280304Sjkim /* flip two last blocks */ 481280304Sjkim memcpy(nistvector + len, vector + len + 16, tail); 482280304Sjkim memcpy(nistvector + len + tail, vector + len, 16); 483280304Sjkim len += 16 + tail; 484280304Sjkim tail = 16; 485238384Sjkim 486280304Sjkim /* test block-based encryption */ 487280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 488280304Sjkim CRYPTO_nistcts128_encrypt_block(test_input, ciphertext, len, &encks, iv, 489280304Sjkim (block128_f) AES_encrypt); 490280304Sjkim if (memcmp(ciphertext, nistvector, len)) 491280304Sjkim fprintf(stderr, "output_%d mismatch\n", len), exit(1); 492280304Sjkim if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 493280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(1); 494238384Sjkim 495280304Sjkim /* test block-based decryption */ 496280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 497280304Sjkim CRYPTO_nistcts128_decrypt_block(ciphertext, cleartext, len, &decks, iv, 498280304Sjkim (block128_f) AES_decrypt); 499280304Sjkim if (memcmp(cleartext, test_input, len)) 500280304Sjkim fprintf(stderr, "input_%d mismatch\n", len), exit(2); 501280304Sjkim if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 502280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(2); 503238384Sjkim 504280304Sjkim /* test streamed encryption */ 505280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 506280304Sjkim CRYPTO_nistcts128_encrypt(test_input, ciphertext, len, &encks, iv, 507280304Sjkim (cbc128_f) AES_cbc_encrypt); 508280304Sjkim if (memcmp(ciphertext, nistvector, len)) 509280304Sjkim fprintf(stderr, "output_%d mismatch\n", len), exit(3); 510280304Sjkim if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 511280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(3); 512238384Sjkim 513280304Sjkim /* test streamed decryption */ 514280304Sjkim memcpy(iv, test_iv, sizeof(test_iv)); 515280304Sjkim CRYPTO_nistcts128_decrypt(ciphertext, cleartext, len, &decks, iv, 516280304Sjkim (cbc128_f) AES_cbc_encrypt); 517280304Sjkim if (memcmp(cleartext, test_input, len)) 518280304Sjkim fprintf(stderr, "input_%d mismatch\n", len), exit(4); 519280304Sjkim if (memcmp(iv, nistvector + len - tail, sizeof(iv))) 520280304Sjkim fprintf(stderr, "iv_%d mismatch\n", len), exit(4); 521238384Sjkim} 522238384Sjkim 523238384Sjkimint main() 524238384Sjkim{ 525280304Sjkim AES_set_encrypt_key(test_key, 128, &encks); 526280304Sjkim AES_set_decrypt_key(test_key, 128, &decks); 527238384Sjkim 528280304Sjkim test_vector(vector_17, sizeof(vector_17)); 529280304Sjkim test_vector(vector_31, sizeof(vector_31)); 530280304Sjkim test_vector(vector_32, sizeof(vector_32)); 531280304Sjkim test_vector(vector_47, sizeof(vector_47)); 532280304Sjkim test_vector(vector_48, sizeof(vector_48)); 533280304Sjkim test_vector(vector_64, sizeof(vector_64)); 534238384Sjkim 535280304Sjkim test_nistvector(vector_17, sizeof(vector_17)); 536280304Sjkim test_nistvector(vector_31, sizeof(vector_31)); 537280304Sjkim test_nistvector(vector_32, sizeof(vector_32)); 538280304Sjkim test_nistvector(vector_47, sizeof(vector_47)); 539280304Sjkim test_nistvector(vector_48, sizeof(vector_48)); 540280304Sjkim test_nistvector(vector_64, sizeof(vector_64)); 541238384Sjkim 542280304Sjkim return 0; 543238384Sjkim} 544238384Sjkim#endif 545