1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <string.h>
11e1051a39Sopenharmony_ci#include <openssl/crypto.h>
12e1051a39Sopenharmony_ci#include "crypto/modes.h"
13e1051a39Sopenharmony_ci
14e1051a39Sopenharmony_ci#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT)
15e1051a39Sopenharmony_citypedef size_t size_t_aX __attribute((__aligned__(1)));
16e1051a39Sopenharmony_ci#else
17e1051a39Sopenharmony_citypedef size_t size_t_aX;
18e1051a39Sopenharmony_ci#endif
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_ci/*
21e1051a39Sopenharmony_ci * The input and output encrypted as though 128bit ofb mode is being used.
22e1051a39Sopenharmony_ci * The extra state information to record how much of the 128bit block we have
23e1051a39Sopenharmony_ci * used is contained in *num;
24e1051a39Sopenharmony_ci */
25e1051a39Sopenharmony_civoid CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out,
26e1051a39Sopenharmony_ci                           size_t len, const void *key,
27e1051a39Sopenharmony_ci                           unsigned char ivec[16], int *num, block128_f block)
28e1051a39Sopenharmony_ci{
29e1051a39Sopenharmony_ci    unsigned int n;
30e1051a39Sopenharmony_ci    size_t l = 0;
31e1051a39Sopenharmony_ci
32e1051a39Sopenharmony_ci    if (*num < 0) {
33e1051a39Sopenharmony_ci        /* There is no good way to signal an error return from here */
34e1051a39Sopenharmony_ci        *num = -1;
35e1051a39Sopenharmony_ci        return;
36e1051a39Sopenharmony_ci    }
37e1051a39Sopenharmony_ci    n = *num;
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ci#if !defined(OPENSSL_SMALL_FOOTPRINT)
40e1051a39Sopenharmony_ci    if (16 % sizeof(size_t) == 0) { /* always true actually */
41e1051a39Sopenharmony_ci        do {
42e1051a39Sopenharmony_ci            while (n && len) {
43e1051a39Sopenharmony_ci                *(out++) = *(in++) ^ ivec[n];
44e1051a39Sopenharmony_ci                --len;
45e1051a39Sopenharmony_ci                n = (n + 1) % 16;
46e1051a39Sopenharmony_ci            }
47e1051a39Sopenharmony_ci# if defined(STRICT_ALIGNMENT)
48e1051a39Sopenharmony_ci            if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) !=
49e1051a39Sopenharmony_ci                0)
50e1051a39Sopenharmony_ci                break;
51e1051a39Sopenharmony_ci# endif
52e1051a39Sopenharmony_ci            while (len >= 16) {
53e1051a39Sopenharmony_ci                (*block) (ivec, ivec, key);
54e1051a39Sopenharmony_ci                for (; n < 16; n += sizeof(size_t))
55e1051a39Sopenharmony_ci                    *(size_t_aX *)(out + n) =
56e1051a39Sopenharmony_ci                        *(size_t_aX *)(in + n)
57e1051a39Sopenharmony_ci                        ^ *(size_t_aX *)(ivec + n);
58e1051a39Sopenharmony_ci                len -= 16;
59e1051a39Sopenharmony_ci                out += 16;
60e1051a39Sopenharmony_ci                in += 16;
61e1051a39Sopenharmony_ci                n = 0;
62e1051a39Sopenharmony_ci            }
63e1051a39Sopenharmony_ci            if (len) {
64e1051a39Sopenharmony_ci                (*block) (ivec, ivec, key);
65e1051a39Sopenharmony_ci                while (len--) {
66e1051a39Sopenharmony_ci                    out[n] = in[n] ^ ivec[n];
67e1051a39Sopenharmony_ci                    ++n;
68e1051a39Sopenharmony_ci                }
69e1051a39Sopenharmony_ci            }
70e1051a39Sopenharmony_ci            *num = n;
71e1051a39Sopenharmony_ci            return;
72e1051a39Sopenharmony_ci        } while (0);
73e1051a39Sopenharmony_ci    }
74e1051a39Sopenharmony_ci    /* the rest would be commonly eliminated by x86* compiler */
75e1051a39Sopenharmony_ci#endif
76e1051a39Sopenharmony_ci    while (l < len) {
77e1051a39Sopenharmony_ci        if (n == 0) {
78e1051a39Sopenharmony_ci            (*block) (ivec, ivec, key);
79e1051a39Sopenharmony_ci        }
80e1051a39Sopenharmony_ci        out[l] = in[l] ^ ivec[n];
81e1051a39Sopenharmony_ci        ++l;
82e1051a39Sopenharmony_ci        n = (n + 1) % 16;
83e1051a39Sopenharmony_ci    }
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci    *num = n;
86e1051a39Sopenharmony_ci}
87