| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2018-04-03 20:57:12 +08:00
										 |  |  |  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-06 20:23:18 +08:00
										 |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  |  * 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
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2015-05-14 22:56:48 +08:00
										 |  |  | #include "internal/cryptlib.h"
 | 
					
						
							| 
									
										
										
										
											1999-04-24 06:13:45 +08:00
										 |  |  | #include <openssl/buffer.h>
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * LIMIT_BEFORE_EXPANSION is the maximum n such that (n+3)/3*4 < 2**31. That | 
					
						
							|  |  |  |  * function is applied in several functions in this file and this limit | 
					
						
							|  |  |  |  * ensures that the result fits in an int. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-04-20 00:19:56 +08:00
										 |  |  | #define LIMIT_BEFORE_EXPANSION 0x5ffffffc
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  | BUF_MEM *BUF_MEM_new_ex(unsigned long flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BUF_MEM *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = BUF_MEM_new(); | 
					
						
							|  |  |  |     if (ret != NULL) | 
					
						
							|  |  |  |         ret->flags = flags; | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | BUF_MEM *BUF_MEM_new(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     BUF_MEM *ret; | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-03 21:15:26 +08:00
										 |  |  |     ret = OPENSSL_zalloc(sizeof(*ret)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (ret == NULL) { | 
					
						
							|  |  |  |         BUFerr(BUF_F_BUF_MEM_NEW, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-20 05:31:43 +08:00
										 |  |  | void BUF_MEM_free(BUF_MEM *a) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-28 04:25:08 +08:00
										 |  |  |     if (a == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (a->data != NULL) { | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  |         if (a->flags & BUF_MEM_FLAG_SECURE) | 
					
						
							| 
									
										
										
										
											2017-07-29 03:59:07 +08:00
										 |  |  |             OPENSSL_secure_clear_free(a->data, a->max); | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  |         else | 
					
						
							|  |  |  |             OPENSSL_clear_free(a->data, a->max); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     OPENSSL_free(a); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  | /* Allocate a block of secure memory; copy over old data if there
 | 
					
						
							|  |  |  |  * was any, and then free it. */ | 
					
						
							|  |  |  | static char *sec_alloc_realloc(BUF_MEM *str, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     char *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = OPENSSL_secure_malloc(len); | 
					
						
							|  |  |  |     if (str->data != NULL) { | 
					
						
							| 
									
										
										
										
											2017-07-10 03:22:26 +08:00
										 |  |  |         if (ret != NULL) { | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  |             memcpy(ret, str->data, str->length); | 
					
						
							| 
									
										
										
										
											2017-07-29 03:59:07 +08:00
										 |  |  |             OPENSSL_secure_clear_free(str->data, str->length); | 
					
						
							| 
									
										
										
										
											2017-07-10 03:22:26 +08:00
										 |  |  |             str->data = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-13 21:02:24 +08:00
										 |  |  | size_t BUF_MEM_grow(BUF_MEM *str, size_t len) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     char *ret; | 
					
						
							|  |  |  |     size_t n; | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (str->length >= len) { | 
					
						
							|  |  |  |         str->length = len; | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return len; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (str->max >= len) { | 
					
						
							| 
									
										
										
										
											2016-05-04 18:45:49 +08:00
										 |  |  |         if (str->data != NULL) | 
					
						
							|  |  |  |             memset(&str->data[str->length], 0, len - str->length); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         str->length = len; | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return len; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ | 
					
						
							|  |  |  |     if (len > LIMIT_BEFORE_EXPANSION) { | 
					
						
							|  |  |  |         BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     n = (len + 3) / 3 * 4; | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  |     if ((str->flags & BUF_MEM_FLAG_SECURE)) | 
					
						
							|  |  |  |         ret = sec_alloc_realloc(str, n); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         ret = OPENSSL_realloc(str->data, n); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (ret == NULL) { | 
					
						
							|  |  |  |         BUFerr(BUF_F_BUF_MEM_GROW, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         len = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         str->data = ret; | 
					
						
							|  |  |  |         str->max = n; | 
					
						
							|  |  |  |         memset(&str->data[str->length], 0, len - str->length); | 
					
						
							|  |  |  |         str->length = len; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return len; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-13 21:02:24 +08:00
										 |  |  | size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     char *ret; | 
					
						
							|  |  |  |     size_t n; | 
					
						
							| 
									
										
										
										
											2002-11-13 23:43:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (str->length >= len) { | 
					
						
							| 
									
										
										
										
											2016-05-04 18:45:49 +08:00
										 |  |  |         if (str->data != NULL) | 
					
						
							|  |  |  |             memset(&str->data[len], 0, str->length - len); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         str->length = len; | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return len; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (str->max >= len) { | 
					
						
							|  |  |  |         memset(&str->data[str->length], 0, len - str->length); | 
					
						
							|  |  |  |         str->length = len; | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |         return len; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ | 
					
						
							|  |  |  |     if (len > LIMIT_BEFORE_EXPANSION) { | 
					
						
							|  |  |  |         BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     n = (len + 3) / 3 * 4; | 
					
						
							| 
									
										
										
										
											2015-04-25 04:39:40 +08:00
										 |  |  |     if ((str->flags & BUF_MEM_FLAG_SECURE)) | 
					
						
							|  |  |  |         ret = sec_alloc_realloc(str, n); | 
					
						
							|  |  |  |     else | 
					
						
							| 
									
										
										
										
											2015-12-17 05:51:12 +08:00
										 |  |  |         ret = OPENSSL_clear_realloc(str->data, str->max, n); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (ret == NULL) { | 
					
						
							|  |  |  |         BUFerr(BUF_F_BUF_MEM_GROW_CLEAN, ERR_R_MALLOC_FAILURE); | 
					
						
							|  |  |  |         len = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         str->data = ret; | 
					
						
							|  |  |  |         str->max = n; | 
					
						
							|  |  |  |         memset(&str->data[str->length], 0, len - str->length); | 
					
						
							|  |  |  |         str->length = len; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-17 22:04:09 +08:00
										 |  |  |     return len; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-11-13 23:43:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-01 22:26:18 +08:00
										 |  |  | void BUF_reverse(unsigned char *out, const unsigned char *in, size_t size) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     if (in) { | 
					
						
							|  |  |  |         out += size - 1; | 
					
						
							|  |  |  |         for (i = 0; i < size; i++) | 
					
						
							|  |  |  |             *out-- = *in++; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         unsigned char *q; | 
					
						
							|  |  |  |         char c; | 
					
						
							|  |  |  |         q = out + size - 1; | 
					
						
							|  |  |  |         for (i = 0; i < size / 2; i++) { | 
					
						
							|  |  |  |             c = *q; | 
					
						
							|  |  |  |             *q-- = *out; | 
					
						
							|  |  |  |             *out++ = c; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |