summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2026-06-09 12:29:47 +0000
committertb <>2026-06-09 12:29:47 +0000
commit329187ca76781997d3a01eafa23caac7f93779f7 (patch)
tree0668d9b6df43809007da7636c70b7dc4dd1741f2
parent256315fc6aeff5ec985bfee63fae84e6cafc4555 (diff)
downloadopenbsd-329187ca76781997d3a01eafa23caac7f93779f7.tar.gz
openbsd-329187ca76781997d3a01eafa23caac7f93779f7.tar.bz2
openbsd-329187ca76781997d3a01eafa23caac7f93779f7.zip
Add some missing bounds checks to ASN1_mbstring_copy()
If the in string is unreasonably long, assigning strlen(in) to an int may overflow, so exclude this situation. Moreover, the code would unconditionally multiply nchar by 2 or 4, which could again overflow an int. Check for this situation and error out to avoid an out of bounds write. More may be needed in here, which will be revisited later. Based on a diff by Viktor Dukhovni via OpenSSL.
-rw-r--r--src/lib/libcrypto/asn1/a_mbstr.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/lib/libcrypto/asn1/a_mbstr.c b/src/lib/libcrypto/asn1/a_mbstr.c
index 38398ad1d1..21368543ce 100644
--- a/src/lib/libcrypto/asn1/a_mbstr.c
+++ b/src/lib/libcrypto/asn1/a_mbstr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: a_mbstr.c,v 1.28 2025/05/10 05:54:38 tb Exp $ */ 1/* $OpenBSD: a_mbstr.c,v 1.29 2026/06/09 12:29:47 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 1999. 3 * project 1999.
4 */ 4 */
@@ -57,6 +57,7 @@
57 */ 57 */
58 58
59#include <ctype.h> 59#include <ctype.h>
60#include <limits.h>
60#include <stdio.h> 61#include <stdio.h>
61#include <string.h> 62#include <string.h>
62 63
@@ -105,8 +106,16 @@ ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
105 int nchar; 106 int nchar;
106 int (*cpyfunc)(unsigned long, void *) = NULL; 107 int (*cpyfunc)(unsigned long, void *) = NULL;
107 108
108 if (len < 0) 109 if (len < 0) {
109 len = strlen((const char *)in); 110 size_t length;
111
112 if ((length = strlen((const char *)in)) >= INT_MAX) {
113 ASN1error(ASN1_R_STRING_TOO_LONG);
114 return -1;
115 }
116 len = length;
117 }
118
110 if (!mask) 119 if (!mask)
111 mask = DIRSTRING_TYPE; 120 mask = DIRSTRING_TYPE;
112 121
@@ -221,11 +230,19 @@ ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
221 break; 230 break;
222 231
223 case MBSTRING_BMP: 232 case MBSTRING_BMP:
233 if (nchar > INT_MAX / 2) {
234 ASN1error(ASN1_R_STRING_TOO_LONG);
235 goto err;
236 }
224 outlen = nchar << 1; 237 outlen = nchar << 1;
225 cpyfunc = cpy_bmp; 238 cpyfunc = cpy_bmp;
226 break; 239 break;
227 240
228 case MBSTRING_UNIV: 241 case MBSTRING_UNIV:
242 if (nchar > INT_MAX / 4) {
243 ASN1error(ASN1_R_STRING_TOO_LONG);
244 goto err;
245 }
229 outlen = nchar << 2; 246 outlen = nchar << 2;
230 cpyfunc = cpy_univ; 247 cpyfunc = cpy_univ;
231 break; 248 break;