Latest update.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "ciphercommon_local.h"
|
||||
#include "prov/providercommonerr.h"
|
||||
|
||||
/*
|
||||
* Fills a single block of buffered data from the input, and returns the amount
|
||||
* of data remaining in the input that is a multiple of the blocksize. The buffer
|
||||
* is only filled if it already has some data in it, isn't full already or we
|
||||
* don't have at least one block in the input.
|
||||
*
|
||||
* buf: a buffer of blocksize bytes
|
||||
* buflen: contains the amount of data already in buf on entry. Updated with the
|
||||
* amount of data in buf at the end. On entry *buflen must always be
|
||||
* less than the blocksize
|
||||
* blocksize: size of a block. Must be greater than 0 and a power of 2
|
||||
* in: pointer to a pointer containing the input data
|
||||
* inlen: amount of input data available
|
||||
*
|
||||
* On return buf is filled with as much data as possible up to a full block,
|
||||
* *buflen is updated containing the amount of data in buf. *in is updated to
|
||||
* the new location where input data should be read from, *inlen is updated with
|
||||
* the remaining amount of data in *in. Returns the largest value <= *inlen
|
||||
* which is a multiple of the blocksize.
|
||||
*/
|
||||
size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen)
|
||||
{
|
||||
size_t blockmask = ~(blocksize - 1);
|
||||
|
||||
assert(*buflen <= blocksize);
|
||||
assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0);
|
||||
|
||||
if (*buflen != blocksize && (*buflen != 0 || *inlen < blocksize)) {
|
||||
size_t bufremain = blocksize - *buflen;
|
||||
|
||||
if (*inlen < bufremain)
|
||||
bufremain = *inlen;
|
||||
memcpy(buf + *buflen, *in, bufremain);
|
||||
*in += bufremain;
|
||||
*inlen -= bufremain;
|
||||
*buflen += bufremain;
|
||||
}
|
||||
|
||||
return *inlen & blockmask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills the buffer with trailing data from an encryption/decryption that didn't
|
||||
* fit into a full block.
|
||||
*/
|
||||
int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
|
||||
const unsigned char **in, size_t *inlen)
|
||||
{
|
||||
if (*inlen == 0)
|
||||
return 1;
|
||||
|
||||
if (*buflen + *inlen > blocksize) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf + *buflen, *in, *inlen);
|
||||
*buflen += *inlen;
|
||||
*inlen = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Pad the final block for encryption */
|
||||
void padblock(unsigned char *buf, size_t *buflen, size_t blocksize)
|
||||
{
|
||||
size_t i;
|
||||
unsigned char pad = (unsigned char)(blocksize - *buflen);
|
||||
|
||||
for (i = *buflen; i < blocksize; i++)
|
||||
buf[i] = pad;
|
||||
}
|
||||
|
||||
int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
|
||||
{
|
||||
size_t pad, i;
|
||||
size_t len = *buflen;
|
||||
|
||||
if(len != blocksize) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following assumes that the ciphertext has been authenticated.
|
||||
* Otherwise it provides a padding oracle.
|
||||
*/
|
||||
pad = buf[blocksize - 1];
|
||||
if (pad == 0 || pad > blocksize) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < pad; i++) {
|
||||
if (buf[--len] != pad) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*buflen = len;
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user