]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/common/ciphers/block.c
Implement support for AES-256-ECB in the default provider
[thirdparty/openssl.git] / providers / common / ciphers / block.c
1 /*
2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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 <string.h>
11 #include <openssl/evp.h>
12 #include <openssl/err.h>
13 #include "ciphers_locl.h"
14 #include <assert.h>
15
16 /*
17 * Fills a single block of buffered data from the input, and returns the amount
18 * of data remaining in the input that is a multiple of the blocksize. The buffer
19 * is only filled if it already has some data in it, isn't full already or we
20 * don't have at least one block in the input.
21 *
22 * buf: a buffer of blocksize bytes
23 * buflen: contains the amount of data already in buf on entry. Updated with the
24 * amount of data in buf at the end. On entry *buflen must always be
25 * less than the blocksize
26 * blocksize: size of a block. Must be greater than 0 and a power of 2
27 * in: pointer to a pointer containing the input data
28 * inlen: amount of input data available
29 *
30 * On return buf is filled with as much data as possible up to a full block,
31 * *buflen is updated containing the amount of data in buf. *in is updated to
32 * the new location where input data should be read from, *inlen is updated with
33 * the remaining amount of data in *in. Returns the largest value <= *inlen
34 * which is a multiple of the blocksize.
35 */
36 size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
37 const unsigned char **in, size_t *inlen)
38 {
39 size_t blockmask = ~(blocksize - 1);
40
41 assert(*buflen <= blocksize);
42 assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
43
44 if (*buflen != blocksize && (*buflen != 0 || *inlen < blocksize)) {
45 size_t bufremain = blocksize - *buflen;
46
47 if (*inlen < bufremain)
48 bufremain = *inlen;
49 memcpy(buf + *buflen, *in, bufremain);
50 *in += bufremain;
51 *inlen -= bufremain;
52 *buflen += bufremain;
53 }
54
55 return *inlen & blockmask;
56 }
57
58 /*
59 * Fills the buffer with trailing data from an encryption/decryption that didn't
60 * fit into a full block.
61 */
62 int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
63 const unsigned char **in, size_t *inlen)
64 {
65 if (*inlen == 0)
66 return 1;
67
68 if (*buflen + *inlen > blocksize)
69 return 0;
70
71 memcpy(buf + *buflen, *in, *inlen);
72 *buflen += *inlen;
73 *inlen = 0;
74
75 return 1;
76 }
77
78 /* Pad the final block for encryption */
79 void padblock(unsigned char *buf, size_t *buflen, size_t blocksize)
80 {
81 size_t i;
82 unsigned char pad = (unsigned char)(blocksize - *buflen);
83
84 for (i = *buflen; i < blocksize; i++)
85 buf[i] = pad;
86 }
87
88 int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
89 {
90 size_t pad, i;
91 size_t len = *buflen;
92
93 if(len != blocksize)
94 return 0;
95
96 /*
97 * The following assumes that the ciphertext has been authenticated.
98 * Otherwise it provides a padding oracle.
99 */
100 pad = buf[blocksize - 1];
101 if (pad == 0 || pad > blocksize) {
102 EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT);
103 return 0;
104 }
105 for (i = 0; i < pad; i++) {
106 if (buf[--len] != pad) {
107 EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT);
108 return 0;
109 }
110 }
111 *buflen = len;
112 return 1;
113 }