diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 3 | ||||
-rw-r--r-- | lib/iov.c | 120 | ||||
-rw-r--r-- | lib/iov.h | 46 | ||||
-rw-r--r-- | lib/libgnutls.map | 3 |
4 files changed, 171 insertions, 1 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index ffc72e4c2c..9fe78afbdc 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -80,7 +80,8 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls system-keys.h urls.c urls.h prf.c auto-verify.c dh-session.c \ cert-session.c handshake-checks.c dtls-sw.c dh-primes.c openpgp_compat.c \ crypto-selftests.c crypto-selftests-pk.c secrets.c extv.c extv.h \ - hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c + hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c \ + iov.c iov.h if WINDOWS COBJECTS += system/keys-win.c diff --git a/lib/iov.c b/lib/iov.c new file mode 100644 index 0000000000..5dc29c54bd --- /dev/null +++ b/lib/iov.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "iov.h" + +/** + * _gnutls_iov_iter_init: + * @iter: the iterator + * @iov: the data buffers + * @iov_count: the number of data buffers + * @block_size: block size to iterate + * + * Initialize the iterator. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise + * an error code is returned + */ +int +_gnutls_iov_iter_init(struct iov_iter_st *iter, + const giovec_t *iov, size_t iov_count, + size_t block_size) +{ + if (unlikely(block_size > MAX_CIPHER_BLOCK_SIZE)) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + iter->iov = iov; + iter->iov_count = iov_count; + iter->iov_index = 0; + iter->iov_offset = 0; + iter->block_size = block_size; + iter->block_offset = 0; + return 0; +} + +/** + * _gnutls_iov_iter_next: + * @iter: the iterator + * @data: the return location of extracted data + * + * Retrieve block(s) pointed by @iter and advance it to the next + * position. It returns the number of consecutive blocks in @data. + * At the end of iteration, 0 is returned. + * + * If the data stored in @iter is not multiple of the block size, the + * remaining data is stored in the "block" field of @iter with the + * size stored in the "block_offset" field. + * + * Returns: On success, a value greater than or equal to zero is + * returned, otherwise a negative error code is returned + */ +ssize_t +_gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data) +{ + while (iter->iov_index < iter->iov_count) { + const giovec_t *iov = &iter->iov[iter->iov_index]; + uint8_t *p = iov->iov_base; + size_t len = iov->iov_len; + size_t block_left; + + if (unlikely(len < iter->iov_offset)) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + len -= iter->iov_offset; + p += iter->iov_offset; + + /* We have at least one full block, return a whole set + * of full blocks immediately. */ + if (iter->block_offset == 0 && len >= iter->block_size) { + if ((len % iter->block_size) == 0) { + iter->iov_index++; + iter->iov_offset = 0; + } else + iter->iov_offset += + len - (len % iter->block_size); + + /* Return the blocks. */ + *data = p; + return len / iter->block_size; + } + + /* We can complete one full block to return. */ + block_left = iter->block_size - iter->block_offset; + if (len >= block_left) { + memcpy(iter->block + iter->block_offset, p, block_left); + iter->iov_offset += block_left; + iter->block_offset = 0; + + /* Return the filled block. */ + *data = iter->block; + return 1; + } + + /* Not enough data for a full block, store in temp + * memory and continue. */ + memcpy(iter->block + iter->block_offset, p, len); + iter->block_offset += len; + iter->iov_index++; + iter->iov_offset = 0; + } + return 0; +} diff --git a/lib/iov.h b/lib/iov.h new file mode 100644 index 0000000000..47fba559ab --- /dev/null +++ b/lib/iov.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_IOV_H +#define GNUTLS_LIB_IOV_H + +#include "gnutls_int.h" + +struct iov_iter_st { + const giovec_t *iov; + size_t iov_count; /* the number of iov */ + size_t iov_index; /* index of the current buffer */ + size_t iov_offset; /* byte offset in the current buffer */ + + uint8_t block[MAX_CIPHER_BLOCK_SIZE]; /* incomplete block for reading */ + size_t block_size; /* actual block size of the cipher */ + size_t block_offset; /* offset in block */ + +}; + +int _gnutls_iov_iter_init(struct iov_iter_st *iter, + const giovec_t *iov, size_t iov_count, + size_t block_size); + +ssize_t _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data); + +#endif /* GNUTLS_LIB_IOV_H */ diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 0f31f4aef4..fc93c0857f 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1384,4 +1384,7 @@ GNUTLS_PRIVATE_3_4 { _gnutls_anti_replay_check; # needed by gnutls-strcodes.c _gnutls_ecc_curve_is_supported; + # needed by tests/iov: + _gnutls_iov_iter_init; + _gnutls_iov_iter_next; } GNUTLS_3_4; |