Add a warning stipulating how things should be coded in ossl_init_base
[openssl.git] / crypto / modes / cbc128.c
1 /*
2  * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <openssl/crypto.h>
11 #include "modes_lcl.h"
12 #include <string.h>
13
14 #if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC)
15 # define STRICT_ALIGNMENT 0
16 #endif
17
18 void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
19                            size_t len, const void *key,
20                            unsigned char ivec[16], block128_f block)
21 {
22     size_t n;
23     const unsigned char *iv = ivec;
24
25 #if !defined(OPENSSL_SMALL_FOOTPRINT)
26     if (STRICT_ALIGNMENT &&
27         ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
28         while (len >= 16) {
29             for (n = 0; n < 16; ++n)
30                 out[n] = in[n] ^ iv[n];
31             (*block) (out, out, key);
32             iv = out;
33             len -= 16;
34             in += 16;
35             out += 16;
36         }
37     } else {
38         while (len >= 16) {
39             for (n = 0; n < 16; n += sizeof(size_t))
40                 *(size_t *)(out + n) =
41                     *(size_t *)(in + n) ^ *(size_t *)(iv + n);
42             (*block) (out, out, key);
43             iv = out;
44             len -= 16;
45             in += 16;
46             out += 16;
47         }
48     }
49 #endif
50     while (len) {
51         for (n = 0; n < 16 && n < len; ++n)
52             out[n] = in[n] ^ iv[n];
53         for (; n < 16; ++n)
54             out[n] = iv[n];
55         (*block) (out, out, key);
56         iv = out;
57         if (len <= 16)
58             break;
59         len -= 16;
60         in += 16;
61         out += 16;
62     }
63     memcpy(ivec, iv, 16);
64 }
65
66 void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
67                            size_t len, const void *key,
68                            unsigned char ivec[16], block128_f block)
69 {
70     size_t n;
71     union {
72         size_t t[16 / sizeof(size_t)];
73         unsigned char c[16];
74     } tmp;
75
76 #if !defined(OPENSSL_SMALL_FOOTPRINT)
77     if (in != out) {
78         const unsigned char *iv = ivec;
79
80         if (STRICT_ALIGNMENT &&
81             ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
82             while (len >= 16) {
83                 (*block) (in, out, key);
84                 for (n = 0; n < 16; ++n)
85                     out[n] ^= iv[n];
86                 iv = in;
87                 len -= 16;
88                 in += 16;
89                 out += 16;
90             }
91         } else if (16 % sizeof(size_t) == 0) { /* always true */
92             while (len >= 16) {
93                 size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv;
94
95                 (*block) (in, out, key);
96                 for (n = 0; n < 16 / sizeof(size_t); n++)
97                     out_t[n] ^= iv_t[n];
98                 iv = in;
99                 len -= 16;
100                 in += 16;
101                 out += 16;
102             }
103         }
104         memcpy(ivec, iv, 16);
105     } else {
106         if (STRICT_ALIGNMENT &&
107             ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
108             unsigned char c;
109             while (len >= 16) {
110                 (*block) (in, tmp.c, key);
111                 for (n = 0; n < 16; ++n) {
112                     c = in[n];
113                     out[n] = tmp.c[n] ^ ivec[n];
114                     ivec[n] = c;
115                 }
116                 len -= 16;
117                 in += 16;
118                 out += 16;
119             }
120         } else if (16 % sizeof(size_t) == 0) { /* always true */
121             while (len >= 16) {
122                 size_t c, *out_t = (size_t *)out, *ivec_t = (size_t *)ivec;
123                 const size_t *in_t = (const size_t *)in;
124
125                 (*block) (in, tmp.c, key);
126                 for (n = 0; n < 16 / sizeof(size_t); n++) {
127                     c = in_t[n];
128                     out_t[n] = tmp.t[n] ^ ivec_t[n];
129                     ivec_t[n] = c;
130                 }
131                 len -= 16;
132                 in += 16;
133                 out += 16;
134             }
135         }
136     }
137 #endif
138     while (len) {
139         unsigned char c;
140         (*block) (in, tmp.c, key);
141         for (n = 0; n < 16 && n < len; ++n) {
142             c = in[n];
143             out[n] = tmp.c[n] ^ ivec[n];
144             ivec[n] = c;
145         }
146         if (len <= 16) {
147             for (; n < 16; ++n)
148                 ivec[n] = in[n];
149             break;
150         }
151         len -= 16;
152         in += 16;
153         out += 16;
154     }
155 }