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