misc/173952: BN_add_word writes one past its buffer when certain values are added to a single word bignum

Jan Mikkelsen janm at transactionware.com
Tue Nov 27 12:30:01 UTC 2012


>Number:         173952
>Category:       misc
>Synopsis:       BN_add_word writes one past its buffer when certain values are added to a single word bignum
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 27 12:30:00 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Jan Mikkelsen
>Release:        9.1-RC3
>Organization:
Transactionware
>Environment:
FreeBSD vanaheim.transactionware.com 9.1-RC3 FreeBSD 9.1-RC3 #0: Sun Nov 25 10:40:45 EST 2012     root at vanaheim.transactionware.com:/home/janm/p4/freebsd-image-std-2011.1/work/base-freebsd/home/janm/p4/freebsd-image-std-2011.1/FreeBSD/src/sys/TW  amd64
>Description:
The function BN_add_word() in crypto/bn/bn_word.c can write one word past the end of the memory pointed to by the 'd' member of the BIGNUM struct when adding a word to a single word bignum.

This has been reported to the OpenSSL people.
>How-To-Repeat:
dc(1) is implemented in terms of BN_*. This will reproduce the problem:

janm at gray: dc $ dc
18446744073709551616 18446744073709551616 / ps
dc: big number failure 306b06b: No such file or directory

>Fix:
My patch below. The OpenSSL people have a different patch; they were more comfortable restructuring the code.


--- //depot/vendor/freebsd/9.1-local/src/crypto/openssl/crypto/bn/bn_word.c	2012-08-13 00:32:35.000000000 1000
+++ /data/scratch/janm/p4/freebsd-image-std-2011.1/FreeBSD/src/crypto/openssl/crypto/bn/bn_word.c	2012-08-13 00:32:35.000000000 1000
@@ -145,9 +145,11 @@
		return(i);
		}
	/* Only expand (and risk failing) if it's possibly necessary */
-	if (((BN_ULONG)(a->d[a->top - 1] + 1) == 0) &&
-			(bn_wexpand(a,a->top+1) == NULL))
-		return(0);
+	if (
+		(((a->top == 1) && (BN_MASK2 - w < a->d[0])) ||
+		 ((a->top > 1) && ((BN_ULONG)(a->d[a->top - 1] + 1) == 0))) &&
+		(bn_wexpand(a,a->top+1) == NULL))
+			return(0);
	i=0;
	for (;;)
		{


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list