11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include <stdio.h> 111cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 121cb0ef41Sopenharmony_ci#include <openssl/buffer.h> 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci/* 151cb0ef41Sopenharmony_ci * LIMIT_BEFORE_EXPANSION is the maximum n such that (n+3)/3*4 < 2**31. That 161cb0ef41Sopenharmony_ci * function is applied in several functions in this file and this limit 171cb0ef41Sopenharmony_ci * ensures that the result fits in an int. 181cb0ef41Sopenharmony_ci */ 191cb0ef41Sopenharmony_ci#define LIMIT_BEFORE_EXPANSION 0x5ffffffc 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ciBUF_MEM *BUF_MEM_new_ex(unsigned long flags) 221cb0ef41Sopenharmony_ci{ 231cb0ef41Sopenharmony_ci BUF_MEM *ret; 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci ret = BUF_MEM_new(); 261cb0ef41Sopenharmony_ci if (ret != NULL) 271cb0ef41Sopenharmony_ci ret->flags = flags; 281cb0ef41Sopenharmony_ci return ret; 291cb0ef41Sopenharmony_ci} 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ciBUF_MEM *BUF_MEM_new(void) 321cb0ef41Sopenharmony_ci{ 331cb0ef41Sopenharmony_ci BUF_MEM *ret; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci ret = OPENSSL_zalloc(sizeof(*ret)); 361cb0ef41Sopenharmony_ci if (ret == NULL) { 371cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 381cb0ef41Sopenharmony_ci return NULL; 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci return ret; 411cb0ef41Sopenharmony_ci} 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_civoid BUF_MEM_free(BUF_MEM *a) 441cb0ef41Sopenharmony_ci{ 451cb0ef41Sopenharmony_ci if (a == NULL) 461cb0ef41Sopenharmony_ci return; 471cb0ef41Sopenharmony_ci if (a->data != NULL) { 481cb0ef41Sopenharmony_ci if (a->flags & BUF_MEM_FLAG_SECURE) 491cb0ef41Sopenharmony_ci OPENSSL_secure_clear_free(a->data, a->max); 501cb0ef41Sopenharmony_ci else 511cb0ef41Sopenharmony_ci OPENSSL_clear_free(a->data, a->max); 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci OPENSSL_free(a); 541cb0ef41Sopenharmony_ci} 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci/* Allocate a block of secure memory; copy over old data if there 571cb0ef41Sopenharmony_ci * was any, and then free it. */ 581cb0ef41Sopenharmony_cistatic char *sec_alloc_realloc(BUF_MEM *str, size_t len) 591cb0ef41Sopenharmony_ci{ 601cb0ef41Sopenharmony_ci char *ret; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci ret = OPENSSL_secure_malloc(len); 631cb0ef41Sopenharmony_ci if (str->data != NULL) { 641cb0ef41Sopenharmony_ci if (ret != NULL) { 651cb0ef41Sopenharmony_ci memcpy(ret, str->data, str->length); 661cb0ef41Sopenharmony_ci OPENSSL_secure_clear_free(str->data, str->length); 671cb0ef41Sopenharmony_ci str->data = NULL; 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci return ret; 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_cisize_t BUF_MEM_grow(BUF_MEM *str, size_t len) 741cb0ef41Sopenharmony_ci{ 751cb0ef41Sopenharmony_ci char *ret; 761cb0ef41Sopenharmony_ci size_t n; 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci if (str->length >= len) { 791cb0ef41Sopenharmony_ci str->length = len; 801cb0ef41Sopenharmony_ci return len; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci if (str->max >= len) { 831cb0ef41Sopenharmony_ci if (str->data != NULL) 841cb0ef41Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 851cb0ef41Sopenharmony_ci str->length = len; 861cb0ef41Sopenharmony_ci return len; 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ 891cb0ef41Sopenharmony_ci if (len > LIMIT_BEFORE_EXPANSION) { 901cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 911cb0ef41Sopenharmony_ci return 0; 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci n = (len + 3) / 3 * 4; 941cb0ef41Sopenharmony_ci if ((str->flags & BUF_MEM_FLAG_SECURE)) 951cb0ef41Sopenharmony_ci ret = sec_alloc_realloc(str, n); 961cb0ef41Sopenharmony_ci else 971cb0ef41Sopenharmony_ci ret = OPENSSL_realloc(str->data, n); 981cb0ef41Sopenharmony_ci if (ret == NULL) { 991cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 1001cb0ef41Sopenharmony_ci len = 0; 1011cb0ef41Sopenharmony_ci } else { 1021cb0ef41Sopenharmony_ci str->data = ret; 1031cb0ef41Sopenharmony_ci str->max = n; 1041cb0ef41Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 1051cb0ef41Sopenharmony_ci str->length = len; 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci return len; 1081cb0ef41Sopenharmony_ci} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_cisize_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len) 1111cb0ef41Sopenharmony_ci{ 1121cb0ef41Sopenharmony_ci char *ret; 1131cb0ef41Sopenharmony_ci size_t n; 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci if (str->length >= len) { 1161cb0ef41Sopenharmony_ci if (str->data != NULL) 1171cb0ef41Sopenharmony_ci memset(&str->data[len], 0, str->length - len); 1181cb0ef41Sopenharmony_ci str->length = len; 1191cb0ef41Sopenharmony_ci return len; 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci if (str->max >= len) { 1221cb0ef41Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 1231cb0ef41Sopenharmony_ci str->length = len; 1241cb0ef41Sopenharmony_ci return len; 1251cb0ef41Sopenharmony_ci } 1261cb0ef41Sopenharmony_ci /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ 1271cb0ef41Sopenharmony_ci if (len > LIMIT_BEFORE_EXPANSION) { 1281cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 1291cb0ef41Sopenharmony_ci return 0; 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci n = (len + 3) / 3 * 4; 1321cb0ef41Sopenharmony_ci if ((str->flags & BUF_MEM_FLAG_SECURE)) 1331cb0ef41Sopenharmony_ci ret = sec_alloc_realloc(str, n); 1341cb0ef41Sopenharmony_ci else 1351cb0ef41Sopenharmony_ci ret = OPENSSL_clear_realloc(str->data, str->max, n); 1361cb0ef41Sopenharmony_ci if (ret == NULL) { 1371cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); 1381cb0ef41Sopenharmony_ci len = 0; 1391cb0ef41Sopenharmony_ci } else { 1401cb0ef41Sopenharmony_ci str->data = ret; 1411cb0ef41Sopenharmony_ci str->max = n; 1421cb0ef41Sopenharmony_ci memset(&str->data[str->length], 0, len - str->length); 1431cb0ef41Sopenharmony_ci str->length = len; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci return len; 1461cb0ef41Sopenharmony_ci} 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_civoid BUF_reverse(unsigned char *out, const unsigned char *in, size_t size) 1491cb0ef41Sopenharmony_ci{ 1501cb0ef41Sopenharmony_ci size_t i; 1511cb0ef41Sopenharmony_ci if (in) { 1521cb0ef41Sopenharmony_ci out += size - 1; 1531cb0ef41Sopenharmony_ci for (i = 0; i < size; i++) 1541cb0ef41Sopenharmony_ci *out-- = *in++; 1551cb0ef41Sopenharmony_ci } else { 1561cb0ef41Sopenharmony_ci unsigned char *q; 1571cb0ef41Sopenharmony_ci char c; 1581cb0ef41Sopenharmony_ci q = out + size - 1; 1591cb0ef41Sopenharmony_ci for (i = 0; i < size / 2; i++) { 1601cb0ef41Sopenharmony_ci c = *q; 1611cb0ef41Sopenharmony_ci *q-- = *out; 1621cb0ef41Sopenharmony_ci *out++ = c; 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci} 166