1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/buffer.h> 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci/* 15e1051a39Sopenharmony_ci * LIMIT_BEFORE_EXPANSION is the maximum n such that (n+3)/3*4 < 2**31. That 16e1051a39Sopenharmony_ci * function is applied in several functions in this file and this limit 17e1051a39Sopenharmony_ci * ensures that the result fits in an int. 18e1051a39Sopenharmony_ci */ 19e1051a39Sopenharmony_ci#define LIMIT_BEFORE_EXPANSION 0x5ffffffc 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ciBUF_MEM *BUF_MEM_new_ex(unsigned long flags) 22e1051a39Sopenharmony_ci{ 23e1051a39Sopenharmony_ci BUF_MEM *ret; 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci ret = BUF_MEM_new(); 26e1051a39Sopenharmony_ci if (ret != NULL) 27e1051a39Sopenharmony_ci ret->flags = flags; 28e1051a39Sopenharmony_ci return ret; 29e1051a39Sopenharmony_ci} 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ciBUF_MEM *BUF_MEM_new(void) 32e1051a39Sopenharmony_ci{ 33e1051a39Sopenharmony_ci BUF_MEM *ret; 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_ci ret = OPENSSL_zalloc(sizeof(*ret)); 36e1051a39Sopenharmony_ci if (ret == NULL) { 37e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 38e1051a39Sopenharmony_ci return NULL; 39e1051a39Sopenharmony_ci } 40e1051a39Sopenharmony_ci return ret; 41e1051a39Sopenharmony_ci} 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_civoid BUF_MEM_free(BUF_MEM *a) 44e1051a39Sopenharmony_ci{ 45e1051a39Sopenharmony_ci if (a == NULL) 46e1051a39Sopenharmony_ci return; 47e1051a39Sopenharmony_ci if (a->data != NULL) { 48e1051a39Sopenharmony_ci if (a->flags & BUF_MEM_FLAG_SECURE) 49e1051a39Sopenharmony_ci OPENSSL_secure_clear_free(a->data, a->max); 50e1051a39Sopenharmony_ci else 51e1051a39Sopenharmony_ci OPENSSL_clear_free(a->data, a->max); 52e1051a39Sopenharmony_ci } 53e1051a39Sopenharmony_ci OPENSSL_free(a); 54e1051a39Sopenharmony_ci} 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci/* Allocate a block of secure memory; copy over old data if there 57e1051a39Sopenharmony_ci * was any, and then free it. */ 58e1051a39Sopenharmony_cistatic char *sec_alloc_realloc(BUF_MEM *str, size_t len) 59e1051a39Sopenharmony_ci{ 60e1051a39Sopenharmony_ci char *ret; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci ret = OPENSSL_secure_malloc(len); 63e1051a39Sopenharmony_ci if (str->data != NULL) { 64e1051a39Sopenharmony_ci if (ret != NULL) { 65e1051a39Sopenharmony_ci memcpy(ret, str->data, str->length); 66e1051a39Sopenharmony_ci OPENSSL_secure_clear_free(str->data, str->length); 67e1051a39Sopenharmony_ci str->data = NULL; 68e1051a39Sopenharmony_ci } 69e1051a39Sopenharmony_ci } 70e1051a39Sopenharmony_ci return ret; 71e1051a39Sopenharmony_ci} 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_cisize_t BUF_MEM_grow(BUF_MEM *str, size_t len) 74e1051a39Sopenharmony_ci{ 75e1051a39Sopenharmony_ci char *ret; 76e1051a39Sopenharmony_ci size_t n; 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ci if (str->length >= len) { 79e1051a39Sopenharmony_ci str->length = len; 80e1051a39Sopenharmony_ci return len; 81e1051a39Sopenharmony_ci } 82e1051a39Sopenharmony_ci if (str->max >= len) { 83e1051a39Sopenharmony_ci if (str->data != NULL) 84e1051a39Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 85e1051a39Sopenharmony_ci str->length = len; 86e1051a39Sopenharmony_ci return len; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ 89e1051a39Sopenharmony_ci if (len > LIMIT_BEFORE_EXPANSION) { 90e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 91e1051a39Sopenharmony_ci return 0; 92e1051a39Sopenharmony_ci } 93e1051a39Sopenharmony_ci n = (len + 3) / 3 * 4; 94e1051a39Sopenharmony_ci if ((str->flags & BUF_MEM_FLAG_SECURE)) 95e1051a39Sopenharmony_ci ret = sec_alloc_realloc(str, n); 96e1051a39Sopenharmony_ci else 97e1051a39Sopenharmony_ci ret = OPENSSL_realloc(str->data, n); 98e1051a39Sopenharmony_ci if (ret == NULL) { 99e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 100e1051a39Sopenharmony_ci len = 0; 101e1051a39Sopenharmony_ci } else { 102e1051a39Sopenharmony_ci str->data = ret; 103e1051a39Sopenharmony_ci str->max = n; 104e1051a39Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 105e1051a39Sopenharmony_ci str->length = len; 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci return len; 108e1051a39Sopenharmony_ci} 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_cisize_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len) 111e1051a39Sopenharmony_ci{ 112e1051a39Sopenharmony_ci char *ret; 113e1051a39Sopenharmony_ci size_t n; 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci if (str->length >= len) { 116e1051a39Sopenharmony_ci if (str->data != NULL) 117e1051a39Sopenharmony_ci memset(&str->data[len], 0, str->length - len); 118e1051a39Sopenharmony_ci str->length = len; 119e1051a39Sopenharmony_ci return len; 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci if (str->max >= len) { 122e1051a39Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 123e1051a39Sopenharmony_ci str->length = len; 124e1051a39Sopenharmony_ci return len; 125e1051a39Sopenharmony_ci } 126e1051a39Sopenharmony_ci /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ 127e1051a39Sopenharmony_ci if (len > LIMIT_BEFORE_EXPANSION) { 128e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 129e1051a39Sopenharmony_ci return 0; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci n = (len + 3) / 3 * 4; 132e1051a39Sopenharmony_ci if ((str->flags & BUF_MEM_FLAG_SECURE)) 133e1051a39Sopenharmony_ci ret = sec_alloc_realloc(str, n); 134e1051a39Sopenharmony_ci else 135e1051a39Sopenharmony_ci ret = OPENSSL_clear_realloc(str->data, str->max, n); 136e1051a39Sopenharmony_ci if (ret == NULL) { 137e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 138e1051a39Sopenharmony_ci len = 0; 139e1051a39Sopenharmony_ci } else { 140e1051a39Sopenharmony_ci str->data = ret; 141e1051a39Sopenharmony_ci str->max = n; 142e1051a39Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 143e1051a39Sopenharmony_ci str->length = len; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci return len; 146e1051a39Sopenharmony_ci} 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_civoid BUF_reverse(unsigned char *out, const unsigned char *in, size_t size) 149e1051a39Sopenharmony_ci{ 150e1051a39Sopenharmony_ci size_t i; 151e1051a39Sopenharmony_ci if (in) { 152e1051a39Sopenharmony_ci out += size - 1; 153e1051a39Sopenharmony_ci for (i = 0; i < size; i++) 154e1051a39Sopenharmony_ci *out-- = *in++; 155e1051a39Sopenharmony_ci } else { 156e1051a39Sopenharmony_ci unsigned char *q; 157e1051a39Sopenharmony_ci char c; 158e1051a39Sopenharmony_ci q = out + size - 1; 159e1051a39Sopenharmony_ci for (i = 0; i < size / 2; i++) { 160e1051a39Sopenharmony_ci c = *q; 161e1051a39Sopenharmony_ci *q-- = *out; 162e1051a39Sopenharmony_ci *out++ = c; 163e1051a39Sopenharmony_ci } 164e1051a39Sopenharmony_ci } 165e1051a39Sopenharmony_ci} 166