int _gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data, size_t data_size) { size_t tot_len = data_size + dest->length; if (data_size == 0) return 0; if (dest->max_length >= tot_len) { size_t unused = MEMSUB (dest->data, dest->allocd); if (dest->max_length - unused <= tot_len) { if (dest->length && dest->data) memmove (dest->allocd, dest->data, dest->length); dest->data = dest->allocd; } memmove (&dest->data[dest->length], data, data_size); dest->length = tot_len; return tot_len; } else { size_t unused = MEMSUB (dest->data, dest->allocd); size_t new_len = MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK); dest->allocd = gnutls_realloc (dest->allocd, new_len); if (dest->allocd == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } dest->max_length = new_len; dest->data = dest->allocd + unused; if (dest->length && dest->data) memmove (dest->allocd, dest->data, dest->length); dest->data = dest->allocd; memcpy (&dest->data[dest->length], data, data_size); dest->length = tot_len; return tot_len; } }
inline static int _gnutls_buffer_insert (gnutls_buffer * buffer, const opaque * _data, size_t data_size) { if ((MEMSUB (_data, buffer->data) >= 0) && (MEMSUB (_data, buffer->data) < (ssize_t) buffer->length)) { /* the given _data is part of the buffer. */ if (data_size > buffer->length) { gnutls_assert (); /* this shouldn't have happened */ return GNUTLS_E_INTERNAL_ERROR; } if (_data == buffer->data) { /* then don't even memmove */ buffer->length = data_size; return 0; } memmove (buffer->data, _data, data_size); buffer->length = data_size; return 0; } if (_gnutls_buffer_append (buffer, _data, data_size) < 0) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
int _gnutls_buffer_resize (gnutls_buffer_st * dest, size_t new_size) { if (dest->max_length >= new_size) { size_t unused = MEMSUB (dest->data, dest->allocd); if (dest->max_length - unused <= new_size) { if (dest->length && dest->data) memmove (dest->allocd, dest->data, dest->length); dest->data = dest->allocd; } return 0; } else { size_t unused = MEMSUB (dest->data, dest->allocd); size_t alloc_len = MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK); dest->allocd = gnutls_realloc (dest->allocd, alloc_len); if (dest->allocd == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } dest->max_length = alloc_len; dest->data = dest->allocd + unused; if (dest->length && dest->data) memmove (dest->allocd, dest->data, dest->length); dest->data = dest->allocd; return 0; } }
int _gnutls_fbase64_decode(const char *header, const uint8_t * data, size_t data_size, gnutls_datum_t * result) { int ret; static const char top[] = "-----BEGIN "; static const char bottom[] = "-----END "; uint8_t *rdata, *kdata; int rdata_size; char pem_header[128]; _gnutls_str_cpy(pem_header, sizeof(pem_header), top); if (header != NULL) _gnutls_str_cat(pem_header, sizeof(pem_header), header); rdata = memmem(data, data_size, pem_header, strlen(pem_header)); if (rdata == NULL) { gnutls_assert(); _gnutls_hard_log("Could not find '%s'\n", pem_header); return GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR; } data_size -= MEMSUB(rdata, data); if (data_size < 4 + strlen(bottom)) { gnutls_assert(); return GNUTLS_E_BASE64_DECODING_ERROR; } kdata = memmem(rdata + 1, data_size - 1, ENDSTR, sizeof(ENDSTR) - 1); /* allow CR as well. */ if (kdata == NULL) { gnutls_assert(); _gnutls_hard_log("Could not find '%s'\n", ENDSTR); return GNUTLS_E_BASE64_DECODING_ERROR; } data_size -= strlen(ENDSTR); data_size -= MEMSUB(kdata, rdata); rdata = kdata + strlen(ENDSTR); /* position is now after the ---BEGIN--- headers */ kdata = memmem(rdata, data_size, bottom, strlen(bottom)); if (kdata == NULL) { gnutls_assert(); return GNUTLS_E_BASE64_DECODING_ERROR; } /* position of kdata is before the ----END--- footer */ rdata_size = MEMSUB(kdata, rdata); if (rdata_size < 4) { gnutls_assert(); return GNUTLS_E_BASE64_DECODING_ERROR; } if ((ret = _gnutls_base64_decode(rdata, rdata_size, result)) < 0) { gnutls_assert(); return GNUTLS_E_BASE64_DECODING_ERROR; } return ret; }