123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /*
- * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
- #include <string.h>
- #include <openssl/crypto.h>
- #include "crypto/modes.h"
- #if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC)
- # define STRICT_ALIGNMENT 0
- #endif
- #if defined(__GNUC__) && !STRICT_ALIGNMENT
- typedef size_t size_t_aX __attribute((__aligned__(1)));
- #else
- typedef size_t size_t_aX;
- #endif
- void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
- size_t len, const void *key,
- unsigned char ivec[16], block128_f block)
- {
- size_t n;
- const unsigned char *iv = ivec;
- if (len == 0)
- return;
- #if !defined(OPENSSL_SMALL_FOOTPRINT)
- if (STRICT_ALIGNMENT &&
- ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
- while (len >= 16) {
- for (n = 0; n < 16; ++n)
- out[n] = in[n] ^ iv[n];
- (*block) (out, out, key);
- iv = out;
- len -= 16;
- in += 16;
- out += 16;
- }
- } else {
- while (len >= 16) {
- for (n = 0; n < 16; n += sizeof(size_t))
- *(size_t_aX *)(out + n) =
- *(size_t_aX *)(in + n) ^ *(size_t_aX *)(iv + n);
- (*block) (out, out, key);
- iv = out;
- len -= 16;
- in += 16;
- out += 16;
- }
- }
- #endif
- while (len) {
- for (n = 0; n < 16 && n < len; ++n)
- out[n] = in[n] ^ iv[n];
- for (; n < 16; ++n)
- out[n] = iv[n];
- (*block) (out, out, key);
- iv = out;
- if (len <= 16)
- break;
- len -= 16;
- in += 16;
- out += 16;
- }
- if (ivec != iv)
- memcpy(ivec, iv, 16);
- }
- void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
- size_t len, const void *key,
- unsigned char ivec[16], block128_f block)
- {
- size_t n;
- union {
- size_t t[16 / sizeof(size_t)];
- unsigned char c[16];
- } tmp;
- if (len == 0)
- return;
- #if !defined(OPENSSL_SMALL_FOOTPRINT)
- if (in != out) {
- const unsigned char *iv = ivec;
- if (STRICT_ALIGNMENT &&
- ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
- while (len >= 16) {
- (*block) (in, out, key);
- for (n = 0; n < 16; ++n)
- out[n] ^= iv[n];
- iv = in;
- len -= 16;
- in += 16;
- out += 16;
- }
- } else if (16 % sizeof(size_t) == 0) { /* always true */
- while (len >= 16) {
- size_t_aX *out_t = (size_t_aX *)out;
- size_t_aX *iv_t = (size_t_aX *)iv;
- (*block) (in, out, key);
- for (n = 0; n < 16 / sizeof(size_t); n++)
- out_t[n] ^= iv_t[n];
- iv = in;
- len -= 16;
- in += 16;
- out += 16;
- }
- }
- if (ivec != iv)
- memcpy(ivec, iv, 16);
- } else {
- if (STRICT_ALIGNMENT &&
- ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
- unsigned char c;
- while (len >= 16) {
- (*block) (in, tmp.c, key);
- for (n = 0; n < 16; ++n) {
- c = in[n];
- out[n] = tmp.c[n] ^ ivec[n];
- ivec[n] = c;
- }
- len -= 16;
- in += 16;
- out += 16;
- }
- } else if (16 % sizeof(size_t) == 0) { /* always true */
- while (len >= 16) {
- size_t c;
- size_t_aX *out_t = (size_t_aX *)out;
- size_t_aX *ivec_t = (size_t_aX *)ivec;
- const size_t_aX *in_t = (const size_t_aX *)in;
- (*block) (in, tmp.c, key);
- for (n = 0; n < 16 / sizeof(size_t); n++) {
- c = in_t[n];
- out_t[n] = tmp.t[n] ^ ivec_t[n];
- ivec_t[n] = c;
- }
- len -= 16;
- in += 16;
- out += 16;
- }
- }
- }
- #endif
- while (len) {
- unsigned char c;
- (*block) (in, tmp.c, key);
- for (n = 0; n < 16 && n < len; ++n) {
- c = in[n];
- out[n] = tmp.c[n] ^ ivec[n];
- ivec[n] = c;
- }
- if (len <= 16) {
- for (; n < 16; ++n)
- ivec[n] = in[n];
- break;
- }
- len -= 16;
- in += 16;
- out += 16;
- }
- }
|