Coverage Report

Created: 2025-06-13 06:58

/src/openssl30/providers/implementations/ciphers/ciphercommon_block.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2019-2021 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 <assert.h>
11
/* For SSL3_VERSION, TLS1_VERSION etc */
12
#include <openssl/prov_ssl.h>
13
#include <openssl/rand.h>
14
#include <openssl/proverr.h>
15
#include "internal/constant_time.h"
16
#include "ciphercommon_local.h"
17
18
/* Functions defined in ssl/tls_pad.c */
19
int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
20
                                    size_t origreclen,
21
                                    unsigned char *recdata,
22
                                    unsigned char **mac,
23
                                    int *alloced,
24
                                    size_t block_size, size_t mac_size,
25
                                    OSSL_LIB_CTX *libctx);
26
27
int tls1_cbc_remove_padding_and_mac(size_t *reclen,
28
                                    size_t origreclen,
29
                                    unsigned char *recdata,
30
                                    unsigned char **mac,
31
                                    int *alloced,
32
                                    size_t block_size, size_t mac_size,
33
                                    int aead,
34
                                    OSSL_LIB_CTX *libctx);
35
36
/*
37
 * Fills a single block of buffered data from the input, and returns the amount
38
 * of data remaining in the input that is a multiple of the blocksize. The buffer
39
 * is only filled if it already has some data in it, isn't full already or we
40
 * don't have at least one block in the input.
41
 *
42
 * buf: a buffer of blocksize bytes
43
 * buflen: contains the amount of data already in buf on entry. Updated with the
44
 *         amount of data in buf at the end. On entry *buflen must always be
45
 *         less than the blocksize
46
 * blocksize: size of a block. Must be greater than 0 and a power of 2
47
 * in: pointer to a pointer containing the input data
48
 * inlen: amount of input data available
49
 *
50
 * On return buf is filled with as much data as possible up to a full block,
51
 * *buflen is updated containing the amount of data in buf. *in is updated to
52
 * the new location where input data should be read from, *inlen is updated with
53
 * the remaining amount of data in *in. Returns the largest value <= *inlen
54
 * which is a multiple of the blocksize.
55
 */
56
size_t ossl_cipher_fillblock(unsigned char *buf, size_t *buflen,
57
                             size_t blocksize,
58
                             const unsigned char **in, size_t *inlen)
59
0
{
60
0
    size_t blockmask = ~(blocksize - 1);
61
0
    size_t bufremain = blocksize - *buflen;
62
63
0
    assert(*buflen <= blocksize);
64
0
    assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
65
66
0
    if (*inlen < bufremain)
67
0
        bufremain = *inlen;
68
0
    memcpy(buf + *buflen, *in, bufremain);
69
0
    *in += bufremain;
70
0
    *inlen -= bufremain;
71
0
    *buflen += bufremain;
72
73
0
    return *inlen & blockmask;
74
0
}
75
76
/*
77
 * Fills the buffer with trailing data from an encryption/decryption that didn't
78
 * fit into a full block.
79
 */
80
int ossl_cipher_trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
81
                             const unsigned char **in, size_t *inlen)
82
810
{
83
810
    if (*inlen == 0)
84
0
        return 1;
85
86
810
    if (*buflen + *inlen > blocksize) {
87
0
        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
88
0
        return 0;
89
0
    }
90
91
810
    memcpy(buf + *buflen, *in, *inlen);
92
810
    *buflen += *inlen;
93
810
    *inlen = 0;
94
95
810
    return 1;
96
810
}
97
98
/* Pad the final block for encryption */
99
void ossl_cipher_padblock(unsigned char *buf, size_t *buflen, size_t blocksize)
100
96
{
101
96
    size_t i;
102
96
    unsigned char pad = (unsigned char)(blocksize - *buflen);
103
104
856
    for (i = *buflen; i < blocksize; i++)
105
760
        buf[i] = pad;
106
96
}
107
108
int ossl_cipher_unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
109
691
{
110
691
    size_t pad, i;
111
691
    size_t len = *buflen;
112
113
691
    if(len != blocksize) {
114
0
        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
115
0
        return 0;
116
0
    }
117
118
    /*
119
     * The following assumes that the ciphertext has been authenticated.
120
     * Otherwise it provides a padding oracle.
121
     */
122
691
    pad = buf[blocksize - 1];
123
691
    if (pad == 0 || pad > blocksize) {
124
16
        ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
125
16
        return 0;
126
16
    }
127
5.74k
    for (i = 0; i < pad; i++) {
128
5.08k
        if (buf[--len] != pad) {
129
15
            ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
130
15
            return 0;
131
15
        }
132
5.08k
    }
133
660
    *buflen = len;
134
660
    return 1;
135
675
}
136
137
/*-
138
 * ossl_cipher_tlsunpadblock removes the CBC padding from the decrypted, TLS, CBC
139
 * record in constant time. Also removes the MAC from the record in constant
140
 * time.
141
 *
142
 * libctx: Our library context
143
 * tlsversion: The TLS version in use, e.g. SSL3_VERSION, TLS1_VERSION, etc
144
 * buf: The decrypted TLS record data
145
 * buflen: The length of the decrypted TLS record data. Updated with the new
146
 *         length after the padding is removed
147
 * block_size: the block size of the cipher used to encrypt the record.
148
 * mac: Location to store the pointer to the MAC
149
 * alloced: Whether the MAC is stored in a newly allocated buffer, or whether
150
 *          *mac points into *buf
151
 * macsize: the size of the MAC inside the record (or 0 if there isn't one)
152
 * aead: whether this is an aead cipher
153
 * returns:
154
 *   0: (in non-constant time) if the record is publicly invalid.
155
 *   1: (in constant time) Record is publicly valid. If padding is invalid then
156
 *      the mac is random
157
 */
158
int ossl_cipher_tlsunpadblock(OSSL_LIB_CTX *libctx, unsigned int tlsversion,
159
                              unsigned char *buf, size_t *buflen,
160
                              size_t blocksize,
161
                              unsigned char **mac, int *alloced, size_t macsize,
162
                              int aead)
163
52.3k
{
164
52.3k
    int ret;
165
166
52.3k
    switch (tlsversion) {
167
7.98k
    case SSL3_VERSION:
168
7.98k
        return ssl3_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
169
7.98k
                                               alloced, blocksize, macsize,
170
7.98k
                                               libctx);
171
172
488
    case TLS1_2_VERSION:
173
29.5k
    case DTLS1_2_VERSION:
174
29.5k
    case TLS1_1_VERSION:
175
44.1k
    case DTLS1_VERSION:
176
44.1k
    case DTLS1_BAD_VER:
177
        /* Remove the explicit IV */
178
44.1k
        buf += blocksize;
179
44.1k
        *buflen -= blocksize;
180
        /* Fall through */
181
44.3k
    case TLS1_VERSION:
182
44.3k
        ret = tls1_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
183
44.3k
                                              alloced, blocksize, macsize,
184
44.3k
                                              aead, libctx);
185
44.3k
        return ret;
186
187
0
    default:
188
0
        return 0;
189
52.3k
    }
190
52.3k
}