From cc6dc9b2294f7dd59899452470b4bbeaed1eb57d Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
Date: Fri, 7 Mar 2014 10:30:37 +0100
Subject: [PATCH] SPARC T4 assembly pack: treat zero input length in CBC.

The problem is that OpenSSH calls EVP_Cipher, which is not as
protective as EVP_CipherUpdate. Formally speaking we ought to
do more checks in *_cipher methods, including rejecting
lengths not divisible by block size (unless ciphertext stealing
is in place). But for now I implement check for zero length in
low-level based on precedent.

PR: 3087, 2775
(cherry picked from commit 5e44c144e649a53bae2724b34d908f6cb26b01ed)
---
 crypto/des/asm/dest4-sparcv9.pl | 15 +++++++++++++++
 crypto/perlasm/sparcv9_modes.pl |  6 ++++++
 2 files changed, 21 insertions(+)

diff --git a/crypto/des/asm/dest4-sparcv9.pl b/crypto/des/asm/dest4-sparcv9.pl
index 8a4c71009..1dc60243d 100644
--- a/crypto/des/asm/dest4-sparcv9.pl
+++ b/crypto/des/asm/dest4-sparcv9.pl
@@ -94,6 +94,9 @@ $code.=<<___;
 .globl	des_t4_cbc_encrypt
 .align	32
 des_t4_cbc_encrypt:
+	cmp		$len, 0
+	be,pn		$::size_t_cc, .Lcbc_abort
+	nop
 	ld		[$ivec + 0], %f0	! load ivec
 	ld		[$ivec + 4], %f1
 
@@ -165,6 +168,9 @@ des_t4_cbc_encrypt:
 	st		%f0, [$ivec + 0]	! write out ivec
 	retl
 	st		%f1, [$ivec + 4]
+.Lcbc_abort:
+	retl
+	nop
 
 .align	16
 2:	ldxa		[$inp]0x82, %g4		! avoid read-after-write hazard
@@ -189,6 +195,9 @@ des_t4_cbc_encrypt:
 .globl	des_t4_cbc_decrypt
 .align	32
 des_t4_cbc_decrypt:
+	cmp		$len, 0
+	be,pn		$::size_t_cc, .Lcbc_abort
+	nop
 	ld		[$ivec + 0], %f2	! load ivec
 	ld		[$ivec + 4], %f3
 
@@ -294,6 +303,9 @@ $code.=<<___;
 .globl	des_t4_ede3_cbc_encrypt
 .align	32
 des_t4_ede3_cbc_encrypt:
+	cmp		$len, 0
+	be,pn		$::size_t_cc, .Lcbc_abort
+	nop
 	ld		[$ivec + 0], %f0	! load ivec
 	ld		[$ivec + 4], %f1
 
@@ -443,6 +455,9 @@ des_t4_ede3_cbc_encrypt:
 .globl	des_t4_ede3_cbc_decrypt
 .align	32
 des_t4_ede3_cbc_decrypt:
+	cmp		$len, 0
+	be,pn		$::size_t_cc, .Lcbc_abort
+	nop
 	ld		[$ivec + 0], %f2	! load ivec
 	ld		[$ivec + 4], %f3
 
diff --git a/crypto/perlasm/sparcv9_modes.pl b/crypto/perlasm/sparcv9_modes.pl
index 6b47bb1af..dc55b34e4 100644
--- a/crypto/perlasm/sparcv9_modes.pl
+++ b/crypto/perlasm/sparcv9_modes.pl
@@ -35,6 +35,8 @@ $::code.=<<___;
 .align	32
 ${alg}${bits}_t4_cbc_encrypt:
 	save		%sp, -$::frame, %sp
+	cmp		$len, 0
+	be,pn		$::size_t_cc, .L${bits}_cbc_enc_abort
 	sub		$inp, $out, $blk_init	! $inp!=$out
 ___
 $::code.=<<___ if (!$::evp);
@@ -123,6 +125,7 @@ $::code.=<<___ if (!$::evp);
 	std		%f2, [$ivec + 8]
 ___
 $::code.=<<___;
+.L${bits}_cbc_enc_abort:
 	ret
 	restore
 
@@ -249,6 +252,8 @@ $::code.=<<___;
 .align	32
 ${alg}${bits}_t4_cbc_decrypt:
 	save		%sp, -$::frame, %sp
+	cmp		$len, 0
+	be,pn		$::size_t_cc, .L${bits}_cbc_dec_abort
 	sub		$inp, $out, $blk_init	! $inp!=$out
 ___
 $::code.=<<___ if (!$::evp);
@@ -341,6 +346,7 @@ $::code.=<<___ if (!$::evp);
 	std		%f14, [$ivec + 8]
 ___
 $::code.=<<___;
+.L${bits}_cbc_dec_abort:
 	ret
 	restore