Home | History | Annotate | Line # | Download | only in ciphers
      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 {
     60     size_t blockmask = ~(blocksize - 1);
     61     size_t bufremain = blocksize - *buflen;
     62 
     63     assert(*buflen <= blocksize);
     64     assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
     65 
     66     if (*inlen < bufremain)
     67         bufremain = *inlen;
     68     memcpy(buf + *buflen, *in, bufremain);
     69     *in += bufremain;
     70     *inlen -= bufremain;
     71     *buflen += bufremain;
     72 
     73     return *inlen & blockmask;
     74 }
     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 {
     83     if (*inlen == 0)
     84         return 1;
     85 
     86     if (*buflen + *inlen > blocksize) {
     87         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
     88         return 0;
     89     }
     90 
     91     memcpy(buf + *buflen, *in, *inlen);
     92     *buflen += *inlen;
     93     *inlen = 0;
     94 
     95     return 1;
     96 }
     97 
     98 /* Pad the final block for encryption */
     99 void ossl_cipher_padblock(unsigned char *buf, size_t *buflen, size_t blocksize)
    100 {
    101     size_t i;
    102     unsigned char pad = (unsigned char)(blocksize - *buflen);
    103 
    104     for (i = *buflen; i < blocksize; i++)
    105         buf[i] = pad;
    106 }
    107 
    108 int ossl_cipher_unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
    109 {
    110     size_t pad, i;
    111     size_t len = *buflen;
    112 
    113     if(len != blocksize) {
    114         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
    115         return 0;
    116     }
    117 
    118     /*
    119      * The following assumes that the ciphertext has been authenticated.
    120      * Otherwise it provides a padding oracle.
    121      */
    122     pad = buf[blocksize - 1];
    123     if (pad == 0 || pad > blocksize) {
    124         ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
    125         return 0;
    126     }
    127     for (i = 0; i < pad; i++) {
    128         if (buf[--len] != pad) {
    129             ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
    130             return 0;
    131         }
    132     }
    133     *buflen = len;
    134     return 1;
    135 }
    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 {
    164     int ret;
    165 
    166     switch (tlsversion) {
    167     case SSL3_VERSION:
    168         return ssl3_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
    169                                                alloced, blocksize, macsize,
    170                                                libctx);
    171 
    172     case TLS1_2_VERSION:
    173     case DTLS1_2_VERSION:
    174     case TLS1_1_VERSION:
    175     case DTLS1_VERSION:
    176     case DTLS1_BAD_VER:
    177         /* Remove the explicit IV */
    178         buf += blocksize;
    179         *buflen -= blocksize;
    180         /* Fall through */
    181     case TLS1_VERSION:
    182         ret = tls1_cbc_remove_padding_and_mac(buflen, *buflen, buf, mac,
    183                                               alloced, blocksize, macsize,
    184                                               aead, libctx);
    185         return ret;
    186 
    187     default:
    188         return 0;
    189     }
    190 }
    191