diff --git a/Configure b/Configure index 5c1d8e6366..fdb75ebbff 100755 --- a/Configure +++ b/Configure @@ -130,7 +130,7 @@ my $x86_elf_asm="$x86_asm:elf"; my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o x86_64-mont5.o x86_64-gf2m.o modexp512-x86_64.o::aes-x86_64.o vpaes-x86_64.o bsaes-x86_64.o aesni-x86_64.o aesni-sha1-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o rc4-md5-x86_64.o:::wp-x86_64.o:cmll-x86_64.o cmll_misc.o:ghash-x86_64.o:e_padlock-x86_64.o"; my $ia64_asm="ia64cpuid.o:bn-ia64.o ia64-mont.o::aes_core.o aes_cbc.o aes-ia64.o::md5-ia64.o:sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o rc4_skey.o:::::ghash-ia64.o::void"; -my $sparcv9_asm="sparcv9cap.o sparccpuid.o:bn-sparcv9.o sparcv9-mont.o sparcv9a-mont.o:des_enc-sparc.o fcrypt_b.o:aes_core.o aes_cbc.o aes-sparcv9.o aest4-sparcv9.o::md5-sparcv9.o:sha1-sparcv9.o sha256-sparcv9.o sha512-sparcv9.o:::::::ghash-sparcv9.o::void"; +my $sparcv9_asm="sparcv9cap.o sparccpuid.o:bn-sparcv9.o sparcv9-mont.o sparcv9a-mont.o:des_enc-sparc.o fcrypt_b.o:aes_core.o aes_cbc.o aes-sparcv9.o aest4-sparcv9.o::md5-sparcv9.o:sha1-sparcv9.o sha256-sparcv9.o sha512-sparcv9.o::::::camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o:ghash-sparcv9.o::void"; my $sparcv8_asm=":sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::::::void"; my $alpha_asm="alphacpuid.o:bn_asm.o alpha-mont.o:::::sha1-alpha.o:::::::ghash-alpha.o::void"; my $mips64_asm=":bn-mips.o mips-mont.o::aes_cbc.o aes-mips.o:::sha1-mips.o sha256-mips.o sha512-mips.o::::::::"; diff --git a/TABLE b/TABLE index b4d78644c0..7ae1b83c47 100644 --- a/TABLE +++ b/TABLE @@ -185,7 +185,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -2627,7 +2627,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -2660,7 +2660,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -4409,7 +4409,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -4607,7 +4607,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -5465,7 +5465,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -5498,7 +5498,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -5597,7 +5597,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void @@ -5630,7 +5630,7 @@ $rc4_obj = $rmd160_obj = $rc5_obj = $wp_obj = -$cmll_obj = +$cmll_obj = camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o $modes_obj = ghash-sparcv9.o $engines_obj = $perlasm_scheme = void diff --git a/crypto/camellia/Makefile b/crypto/camellia/Makefile index 8858dd057d..d39b55390e 100644 --- a/crypto/camellia/Makefile +++ b/crypto/camellia/Makefile @@ -48,6 +48,8 @@ cmll-x86.s: asm/cmll-x86.pl ../perlasm/x86asm.pl $(PERL) asm/cmll-x86.pl $(PERLASM_SCHEME) $(CFLAGS) $(PROCESSOR) > $@ cmll-x86_64.s: asm/cmll-x86_64.pl $(PERL) asm/cmll-x86_64.pl $(PERLASM_SCHEME) > $@ +cmllt4-sparcv9.s: asm/cmllt4-sparcv9.pl + $(PERL) asm/cmllt4-sparcv9.pl $(CFLAGS) > $@ files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/crypto/camellia/asm/cmllt4-sparcv9.pl b/crypto/camellia/asm/cmllt4-sparcv9.pl new file mode 100644 index 0000000000..041922134e --- /dev/null +++ b/crypto/camellia/asm/cmllt4-sparcv9.pl @@ -0,0 +1,932 @@ +#!/usr/bin/env perl + +# ==================================================================== +# Written by David S. Miller and Andy Polyakov +# . The module is licensed under 2-clause BSD +# license. October 2012. All rights reserved. +# ==================================================================== + +###################################################################### +# Camellia for SPARC T4. +# +# As with AES below results [for aligned data] are virtually identical +# to critical path lenths for 3-cycle instruction latency: +# +# 128-bit key 192/256- +# CBC encrypt 4.14/4.21(*) 5.46/5.52 +# (*) numbers after slash are for +# misaligned data. +# +# As with Intel AES-NI, question is if it's possible to improve +# performance of parallelizeable modes by interleaving round +# instructions. In Camellia every instruction is dependent on +# previous, which means that there is place for 2 additional ones +# in between two dependent. Can we expect 3x performance improvement? +# At least one can argue that it should be possible to break 2x +# barrier... For some reason not even 2x appears to be possible: +# +# 128-bit key 192/256- +# CBC decrypt 2.21/2.74 2.99/3.40 +# CTR 2.15/2.68(*) 2.93/3.34 +# (*) numbers after slash are for +# misaligned data. +# +# This is for 2x interleave. But compared to 1x interleave CBC decrypt +# improved by ... 0% for 128-bit key, and 11% for 192/256-bit one. +# So that out-of-order execution logic can take non-interleaved code +# to 1.87x, but can't take 2x interleaved one any further. There +# surely is some explanation... As result 3x interleave was not even +# attempted. Instead an effort was made to share specific modes +# implementations with AES module (therefore sparct4_modes.pl). +# +# To anchor to something else, software C implementation processes +# one byte in 38 cycles with 128-bit key on same processor. + +$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; +push(@INC,"${dir}","${dir}../../perlasm"); +require "sparcv9_modes.pl"; + +$bits=32; +for (@ARGV) { $bits=64 if (/\-m64/ || /\-xarch\=v9/); } +if ($bits==64) { $::bias=2047; $::frame=192; } +else { $::bias=0; $::frame=112; } + +$::evp=1; # if $evp is set to 0, script generates module with +# Camellia_[en|de]crypt, Camellia_set_key and Camellia_cbc_encrypt +# entry points. These are fully compatible with openssl/camellia.h. + +###################################################################### +# single-round subroutines +# +{ +my ($inp,$out,$key,$rounds,$tmp,$mask)=map("%o$_",(0..5)); + +$code=<<___; +.text + +.globl cmll_t4_encrypt +.align 32 +cmll_t4_encrypt: + andcc $inp, 7, %g1 ! is input aligned? + andn $inp, 7, $inp + + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 + + ldx [$inp + 0], %o4 + bz,pt %icc, 1f + ldx [$inp + 8], %o5 + ldx [$inp + 16], $inp + sll %g1, 3, %g1 + sub %g0, %g1, %o3 + sllx %o4, %g1, %o4 + sllx %o5, %g1, %g1 + srlx %o5, %o3, %o5 + srlx $inp, %o3, %o3 + or %o5, %o4, %o4 + or %o3, %g1, %o5 +1: + ld [$key + 272], $rounds ! grandRounds, 3 or 4 + ldd [$key + 16], %f12 + ldd [$key + 24], %f14 + xor %g4, %o4, %o4 + xor %g5, %o5, %o5 + ldd [$key + 32], %f16 + ldd [$key + 40], %f18 + movxtod %o4, %f0 + movxtod %o5, %f2 + ldd [$key + 48], %f20 + ldd [$key + 56], %f22 + sub $rounds, 1, $rounds + ldd [$key + 64], %f24 + ldd [$key + 72], %f26 + add $key, 80, $key + +.Lenc: + camellia_f %f12, %f2, %f0, %f2 + ldd [$key + 0], %f12 + sub $rounds,1,$rounds + camellia_f %f14, %f0, %f2, %f0 + ldd [$key + 8], %f14 + camellia_f %f16, %f2, %f0, %f2 + ldd [$key + 16], %f16 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 24], %f18 + camellia_f %f20, %f2, %f0, %f2 + ldd [$key + 32], %f20 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 40], %f22 + camellia_fl %f24, %f0, %f0 + ldd [$key + 48], %f24 + camellia_fli %f26, %f2, %f2 + ldd [$key + 56], %f26 + brnz,pt $rounds, .Lenc + add $key, 64, $key + + andcc $out, 7, $tmp ! is output aligned? + camellia_f %f12, %f2, %f0, %f2 + camellia_f %f14, %f0, %f2, %f0 + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f20, %f2, %f0, %f4 + camellia_f %f22, %f0, %f4, %f2 + fxor %f24, %f4, %f0 + fxor %f26, %f2, %f2 + + bnz,pn %icc, 2f + nop + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +2: alignaddrl $out, %g0, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + + faligndata %f0, %f0, %f4 + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $mask, $mask + retl + stda %f8, [$out + $mask]0xc0 ! partial store +.type cmll_t4_encrypt,#function +.size cmll_t4_encrypt,.-cmll_t4_encrypt + +.globl cmll_t4_decrypt +.align 32 +cmll_t4_decrypt: + ld [$key + 272], $rounds ! grandRounds, 3 or 4 + andcc $inp, 7, %g1 ! is input aligned? + andn $inp, 7, $inp + + sll $rounds, 6, $rounds + add $rounds, $key, $key + + ldx [$inp + 0], %o4 + bz,pt %icc, 1f + ldx [$inp + 8], %o5 + ldx [$inp + 16], $inp + sll %g1, 3, %g1 + sub %g0, %g1, %g4 + sllx %o4, %g1, %o4 + sllx %o5, %g1, %g1 + srlx %o5, %g4, %o5 + srlx $inp, %g4, %g4 + or %o5, %o4, %o4 + or %g4, %g1, %o5 +1: + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 + ldd [$key - 8], %f12 + ldd [$key - 16], %f14 + xor %g4, %o4, %o4 + xor %g5, %o5, %o5 + ldd [$key - 24], %f16 + ldd [$key - 32], %f18 + movxtod %o4, %f0 + movxtod %o5, %f2 + ldd [$key - 40], %f20 + ldd [$key - 48], %f22 + sub $rounds, 64, $rounds + ldd [$key - 56], %f24 + ldd [$key - 64], %f26 + sub $key, 64, $key + +.Ldec: + camellia_f %f12, %f2, %f0, %f2 + ldd [$key - 8], %f12 + sub $rounds, 64, $rounds + camellia_f %f14, %f0, %f2, %f0 + ldd [$key - 16], %f14 + camellia_f %f16, %f2, %f0, %f2 + ldd [$key - 24], %f16 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key - 32], %f18 + camellia_f %f20, %f2, %f0, %f2 + ldd [$key - 40], %f20 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key - 48], %f22 + camellia_fl %f24, %f0, %f0 + ldd [$key - 56], %f24 + camellia_fli %f26, %f2, %f2 + ldd [$key - 64], %f26 + brnz,pt $rounds, .Ldec + sub $key, 64, $key + + andcc $out, 7, $tmp ! is output aligned? + camellia_f %f12, %f2, %f0, %f2 + camellia_f %f14, %f0, %f2, %f0 + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f20, %f2, %f0, %f4 + camellia_f %f22, %f0, %f4, %f2 + fxor %f26, %f4, %f0 + fxor %f24, %f2, %f2 + + bnz,pn %icc, 2f + nop + + std %f0, [$out + 0] + retl + std %f2, [$out + 8] + +2: alignaddrl $out, %g0, $out + mov 0xff, $mask + srl $mask, $tmp, $mask + + faligndata %f0, %f0, %f4 + faligndata %f0, %f2, %f6 + faligndata %f2, %f2, %f8 + + stda %f4, [$out + $mask]0xc0 ! partial store + std %f6, [$out + 8] + add $out, 16, $out + orn %g0, $mask, $mask + retl + stda %f8, [$out + $mask]0xc0 ! partial store +.type cmll_t4_decrypt,#function +.size cmll_t4_decrypt,.-cmll_t4_decrypt +___ +} + +###################################################################### +# key setup subroutines +# +{ +sub ROTL128 { + my $rot = shift; + + "srlx %o4, 64-$rot, %g4\n\t". + "sllx %o4, $rot, %o4\n\t". + "srlx %o5, 64-$rot, %g5\n\t". + "sllx %o5, $rot, %o5\n\t". + "or %o4, %g5, %o4\n\t". + "or %o5, %g4, %o5"; +} + +my ($inp,$bits,$out,$tmp)=map("%o$_",(0..5)); +$code.=<<___; +.globl cmll_t4_set_key +.align 32 +cmll_t4_set_key: + and $inp, 7, $tmp + alignaddr $inp, %g0, $inp + cmp $bits, 192 + ldd [$inp + 0], %f0 + bl,pt %icc,.L128 + ldd [$inp + 8], %f2 + + be,pt %icc,.L192 + ldd [$inp + 16], %f4 + + brz,pt $tmp, .L256aligned + ldd [$inp + 24], %f6 + + ldd [$inp + 32], %f8 + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 + b .L256aligned + faligndata %f6, %f8, %f6 + +.align 16 +.L192: + brz,a,pt $tmp, .L256aligned + fnot2 %f4, %f6 + + ldd [$inp + 24], %f6 + nop + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + faligndata %f4, %f6, %f4 + fnot2 %f4, %f6 + +.L256aligned: + std %f0, [$out + 0] ! k[0, 1] + fsrc2 %f0, %f28 + std %f2, [$out + 8] ! k[2, 3] + fsrc2 %f2, %f30 + fxor %f4, %f0, %f0 + b .L128key + fxor %f6, %f2, %f2 + +.align 16 +.L128: + brz,pt $tmp, .L128aligned + nop + + ldd [$inp + 16], %f4 + nop + faligndata %f0, %f2, %f0 + faligndata %f2, %f4, %f2 + +.L128aligned: + std %f0, [$out + 0] ! k[0, 1] + fsrc2 %f0, %f28 + std %f2, [$out + 8] ! k[2, 3] + fsrc2 %f2, %f30 + +.L128key: + mov %o7, %o5 +1: call .+8 + add %o7, SIGMA-1b, %o4 + mov %o5, %o7 + + ldd [%o4 + 0], %f16 + ldd [%o4 + 8], %f18 + ldd [%o4 + 16], %f20 + ldd [%o4 + 24], %f22 + + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + fxor %f28, %f0, %f0 + fxor %f30, %f2, %f2 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + + bge,pn %icc, .L256key + nop + std %f0, [$out + 0x10] ! k[ 4, 5] + std %f2, [$out + 0x18] ! k[ 6, 7] + + movdtox %f0, %o4 + movdtox %f2, %o5 + `&ROTL128(15)` + stx %o4, [$out + 0x30] ! k[12, 13] + stx %o5, [$out + 0x38] ! k[14, 15] + `&ROTL128(15)` + stx %o4, [$out + 0x40] ! k[16, 17] + stx %o5, [$out + 0x48] ! k[18, 19] + `&ROTL128(15)` + stx %o4, [$out + 0x60] ! k[24, 25] + `&ROTL128(15)` + stx %o4, [$out + 0x70] ! k[28, 29] + stx %o5, [$out + 0x78] ! k[30, 31] + `&ROTL128(34)` + stx %o4, [$out + 0xa0] ! k[40, 41] + stx %o5, [$out + 0xa8] ! k[42, 43] + `&ROTL128(17)` + stx %o4, [$out + 0xc0] ! k[48, 49] + stx %o5, [$out + 0xc8] ! k[50, 51] + + movdtox %f28, %o4 ! k[ 0, 1] + movdtox %f30, %o5 ! k[ 2, 3] + `&ROTL128(15)` + stx %o4, [$out + 0x20] ! k[ 8, 9] + stx %o5, [$out + 0x28] ! k[10, 11] + `&ROTL128(30)` + stx %o4, [$out + 0x50] ! k[20, 21] + stx %o5, [$out + 0x58] ! k[22, 23] + `&ROTL128(15)` + stx %o5, [$out + 0x68] ! k[26, 27] + `&ROTL128(17)` + stx %o4, [$out + 0x80] ! k[32, 33] + stx %o5, [$out + 0x88] ! k[34, 35] + `&ROTL128(17)` + stx %o4, [$out + 0x90] ! k[36, 37] + stx %o5, [$out + 0x98] ! k[38, 39] + `&ROTL128(17)` + stx %o4, [$out + 0xb0] ! k[44, 45] + stx %o5, [$out + 0xb8] ! k[46, 47] + + mov 3, $tmp + st $tmp, [$out + 0x110] + retl + xor %o0, %o0, %o0 + +.align 16 +.L256key: + ldd [%o4 + 32], %f24 + ldd [%o4 + 40], %f26 + + std %f0, [$out + 0x30] ! k[12, 13] + std %f2, [$out + 0x38] ! k[14, 15] + + fxor %f4, %f0, %f0 + fxor %f6, %f2, %f2 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f26, %f0, %f2, %f0 + + std %f0, [$out + 0x10] ! k[ 4, 5] + std %f2, [$out + 0x18] ! k[ 6, 7] + + movdtox %f0, %o4 + movdtox %f2, %o5 + `&ROTL128(30)` + stx %o4, [$out + 0x50] ! k[20, 21] + stx %o5, [$out + 0x58] ! k[22, 23] + `&ROTL128(30)` + stx %o4, [$out + 0xa0] ! k[40, 41] + stx %o5, [$out + 0xa8] ! k[42, 43] + `&ROTL128(51)` + stx %o4, [$out + 0x100] ! k[64, 65] + stx %o5, [$out + 0x108] ! k[66, 67] + + movdtox %f4, %o4 ! k[ 8, 9] + movdtox %f6, %o5 ! k[10, 11] + `&ROTL128(15)` + stx %o4, [$out + 0x20] ! k[ 8, 9] + stx %o5, [$out + 0x28] ! k[10, 11] + `&ROTL128(15)` + stx %o4, [$out + 0x40] ! k[16, 17] + stx %o5, [$out + 0x48] ! k[18, 19] + `&ROTL128(30)` + stx %o4, [$out + 0x90] ! k[36, 37] + stx %o5, [$out + 0x98] ! k[38, 39] + `&ROTL128(34)` + stx %o4, [$out + 0xd0] ! k[52, 53] + stx %o5, [$out + 0xd8] ! k[54, 55] + ldx [$out + 0x30], %o4 ! k[12, 13] + ldx [$out + 0x38], %o5 ! k[14, 15] + `&ROTL128(15)` + stx %o4, [$out + 0x30] ! k[12, 13] + stx %o5, [$out + 0x38] ! k[14, 15] + `&ROTL128(30)` + stx %o4, [$out + 0x70] ! k[28, 29] + stx %o5, [$out + 0x78] ! k[30, 31] + srlx %o4, 32, %g4 + srlx %o5, 32, %g5 + st %o4, [$out + 0xc0] ! k[48] + st %g5, [$out + 0xc4] ! k[49] + st %o5, [$out + 0xc8] ! k[50] + st %g4, [$out + 0xcc] ! k[51] + `&ROTL128(49)` + stx %o4, [$out + 0xe0] ! k[56, 57] + stx %o5, [$out + 0xe8] ! k[58, 59] + + movdtox %f28, %o4 ! k[ 0, 1] + movdtox %f30, %o5 ! k[ 2, 3] + `&ROTL128(45)` + stx %o4, [$out + 0x60] ! k[24, 25] + stx %o5, [$out + 0x68] ! k[26, 27] + `&ROTL128(15)` + stx %o4, [$out + 0x80] ! k[32, 33] + stx %o5, [$out + 0x88] ! k[34, 35] + `&ROTL128(17)` + stx %o4, [$out + 0xb0] ! k[44, 45] + stx %o5, [$out + 0xb8] ! k[46, 47] + `&ROTL128(34)` + stx %o4, [$out + 0xf0] ! k[60, 61] + stx %o5, [$out + 0xf8] ! k[62, 63] + + mov 4, $tmp + st $tmp, [$out + 0x110] + retl + xor %o0, %o0, %o0 +.type cmll_t4_set_key,#function +.size cmll_t4_set_key,.-cmll_t4_set_key +.align 32 +SIGMA: + .long 0xa09e667f, 0x3bcc908b, 0xb67ae858, 0x4caa73b2 + .long 0xc6ef372f, 0xe94f82be, 0x54ff53a5, 0xf1d36f1c + .long 0x10e527fa, 0xde682d1d, 0xb05688c2, 0xb3e6c1fd +.type SIGMA,#object +.size SIGMA,.-SIGMA +.asciz "Camellia for SPARC T4, David S. Miller, Andy Polyakov" +___ +} + +{{{ +my ($inp,$out,$len,$key,$ivec,$enc)=map("%i$_",(0..5)); +my ($ileft,$iright,$ooff,$omask,$ivoff)=map("%l$_",(1..7)); + +$code.=<<___; +.align 32 +_cmll128_load_enckey: + ldx [$key + 0], %g4 + ldx [$key + 8], %g5 +___ +for ($i=2; $i<26;$i++) { # load key schedule + $code.=<<___; + ldd [$key + `8*$i`], %f`12+2*$i` +___ +} +$code.=<<___; + retl + nop +.type _cmll128_load_enckey,#function +.size _cmll128_load_enckey,.-_cmll128_load_enckey +_cmll256_load_enckey=_cmll128_load_enckey + +.align 32 +_cmll256_load_deckey: + ldd [$key + 64], %f62 + ldd [$key + 72], %f60 + b .Load_deckey + add $key, 64, $key +_cmll128_load_deckey: + ldd [$key + 0], %f60 + ldd [$key + 8], %f62 +.Load_deckey: +___ +for ($i=2; $i<24;$i++) { # load key schedule + $code.=<<___; + ldd [$key + `8*$i`], %f`62-2*$i` +___ +} +$code.=<<___; + ldx [$key + 192], %g4 + retl + ldx [$key + 200], %g5 +.type _cmll256_load_deckey,#function +.size _cmll256_load_deckey,.-_cmll256_load_deckey + +.align 32 +_cmll128_encrypt_1x: +___ +for ($i=0; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 +___ +$code.=<<___ if ($i<2); + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fli %f`16+16*$i+14`, %f2, %f2 +___ +} +$code.=<<___; + camellia_f %f56, %f2, %f0, %f4 + camellia_f %f58, %f0, %f4, %f2 + fxor %f60, %f4, %f0 + retl + fxor %f62, %f2, %f2 +.type _cmll128_encrypt_1x,#function +.size _cmll128_encrypt_1x,.-_cmll128_encrypt_1x +_cmll128_decrypt_1x=_cmll128_encrypt_1x + +.align 32 +_cmll128_encrypt_2x: +___ +for ($i=0; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+0`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+2`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+4`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+6`, %f4, %f6, %f4 +___ +$code.=<<___ if ($i<2); + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+8`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+10`, %f4, %f6, %f4 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fl %f`16+16*$i+12`, %f4, %f4 + camellia_fli %f`16+16*$i+14`, %f2, %f2 + camellia_fli %f`16+16*$i+14`, %f6, %f6 +___ +} +$code.=<<___; + camellia_f %f56, %f2, %f0, %f8 + camellia_f %f56, %f6, %f4, %f10 + camellia_f %f58, %f0, %f8, %f2 + camellia_f %f58, %f4, %f10, %f6 + fxor %f60, %f8, %f0 + fxor %f60, %f10, %f4 + fxor %f62, %f2, %f2 + retl + fxor %f62, %f6, %f6 +.type _cmll128_encrypt_2x,#function +.size _cmll128_encrypt_2x,.-_cmll128_encrypt_2x +_cmll128_decrypt_2x=_cmll128_encrypt_2x + +.align 32 +_cmll256_encrypt_1x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f26, %f0, %f2, %f0 + ldd [$key + 240], %f24 + ldd [$key + 248], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fli %f30, %f2, %f2 + ldd [$key + 256], %f28 + ldd [$key + 264], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fli %f`16+16*$i+14`, %f2, %f2 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 32], %f20 + ldd [$key + 40], %f22 + camellia_f %f24, %f2, %f0, %f4 + camellia_f %f26, %f0, %f4, %f2 + ldd [$key + 48], %f24 + ldd [$key + 56], %f26 + fxor %f28, %f4, %f0 + fxor %f30, %f2, %f2 + ldd [$key + 64], %f28 + retl + ldd [$key + 72], %f30 +.type _cmll256_encrypt_1x,#function +.size _cmll256_encrypt_1x,.-_cmll256_encrypt_1x + +.align 32 +_cmll256_encrypt_2x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key + 208], %f16 + ldd [$key + 216], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key + 224], %f20 + ldd [$key + 232], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f24, %f6, %f4, %f6 + camellia_f %f26, %f0, %f2, %f0 + camellia_f %f26, %f4, %f6, %f4 + ldd [$key + 240], %f24 + ldd [$key + 248], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fl %f28, %f4, %f4 + camellia_fli %f30, %f2, %f2 + camellia_fli %f30, %f6, %f6 + ldd [$key + 256], %f28 + ldd [$key + 264], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+0`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+2`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+4`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+6`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+8`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+10`, %f4, %f6, %f4 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fl %f`16+16*$i+12`, %f4, %f4 + camellia_fli %f`16+16*$i+14`, %f2, %f2 + camellia_fli %f`16+16*$i+14`, %f6, %f6 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key + 16], %f16 + ldd [$key + 24], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key + 32], %f20 + ldd [$key + 40], %f22 + camellia_f %f24, %f2, %f0, %f8 + camellia_f %f24, %f6, %f4, %f10 + camellia_f %f26, %f0, %f8, %f2 + camellia_f %f26, %f4, %f10, %f6 + ldd [$key + 48], %f24 + ldd [$key + 56], %f26 + fxor %f28, %f8, %f0 + fxor %f28, %f10, %f4 + fxor %f30, %f2, %f2 + fxor %f30, %f6, %f6 + ldd [$key + 64], %f28 + retl + ldd [$key + 72], %f30 +.type _cmll256_encrypt_2x,#function +.size _cmll256_encrypt_2x,.-_cmll256_encrypt_2x + +.align 32 +_cmll256_decrypt_1x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key - 8], %f16 + ldd [$key - 16], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key - 24], %f20 + ldd [$key - 32], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f26, %f0, %f2, %f0 + ldd [$key - 40], %f24 + ldd [$key - 48], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fli %f30, %f2, %f2 + ldd [$key - 56], %f28 + ldd [$key - 64], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fli %f`16+16*$i+14`, %f2, %f2 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f18, %f0, %f2, %f0 + ldd [$key + 184], %f16 + ldd [$key + 176], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f22, %f0, %f2, %f0 + ldd [$key + 168], %f20 + ldd [$key + 160], %f22 + camellia_f %f24, %f2, %f0, %f4 + camellia_f %f26, %f0, %f4, %f2 + ldd [$key + 152], %f24 + ldd [$key + 144], %f26 + fxor %f30, %f4, %f0 + fxor %f28, %f2, %f2 + ldd [$key + 136], %f28 + retl + ldd [$key + 128], %f30 +.type _cmll256_decrypt_1x,#function +.size _cmll256_decrypt_1x,.-_cmll256_decrypt_1x + +.align 32 +_cmll256_decrypt_2x: + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key - 8], %f16 + ldd [$key - 16], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key - 24], %f20 + ldd [$key - 32], %f22 + camellia_f %f24, %f2, %f0, %f2 + camellia_f %f24, %f6, %f4, %f6 + camellia_f %f26, %f0, %f2, %f0 + camellia_f %f26, %f4, %f6, %f4 + ldd [$key - 40], %f24 + ldd [$key - 48], %f26 + camellia_fl %f28, %f0, %f0 + camellia_fl %f28, %f4, %f4 + camellia_fli %f30, %f2, %f2 + camellia_fli %f30, %f6, %f6 + ldd [$key - 56], %f28 + ldd [$key - 64], %f30 +___ +for ($i=1; $i<3; $i++) { + $code.=<<___; + camellia_f %f`16+16*$i+0`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+0`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+2`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+2`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+4`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+4`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+6`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+6`, %f4, %f6, %f4 + camellia_f %f`16+16*$i+8`, %f2, %f0, %f2 + camellia_f %f`16+16*$i+8`, %f6, %f4, %f6 + camellia_f %f`16+16*$i+10`, %f0, %f2, %f0 + camellia_f %f`16+16*$i+10`, %f4, %f6, %f4 + camellia_fl %f`16+16*$i+12`, %f0, %f0 + camellia_fl %f`16+16*$i+12`, %f4, %f4 + camellia_fli %f`16+16*$i+14`, %f2, %f2 + camellia_fli %f`16+16*$i+14`, %f6, %f6 +___ +} +$code.=<<___; + camellia_f %f16, %f2, %f0, %f2 + camellia_f %f16, %f6, %f4, %f6 + camellia_f %f18, %f0, %f2, %f0 + camellia_f %f18, %f4, %f6, %f4 + ldd [$key + 184], %f16 + ldd [$key + 176], %f18 + camellia_f %f20, %f2, %f0, %f2 + camellia_f %f20, %f6, %f4, %f6 + camellia_f %f22, %f0, %f2, %f0 + camellia_f %f22, %f4, %f6, %f4 + ldd [$key + 168], %f20 + ldd [$key + 160], %f22 + camellia_f %f24, %f2, %f0, %f8 + camellia_f %f24, %f6, %f4, %f10 + camellia_f %f26, %f0, %f8, %f2 + camellia_f %f26, %f4, %f10, %f6 + ldd [$key + 152], %f24 + ldd [$key + 144], %f26 + fxor %f30, %f8, %f0 + fxor %f30, %f10, %f4 + fxor %f28, %f2, %f2 + fxor %f28, %f6, %f6 + ldd [$key + 136], %f28 + retl + ldd [$key + 128], %f30 +.type _cmll256_decrypt_2x,#function +.size _cmll256_decrypt_2x,.-_cmll256_decrypt_2x +___ + +&alg_cbc_encrypt_implement("cmll",128); +&alg_cbc_encrypt_implement("cmll",256); + +&alg_cbc_decrypt_implement("cmll",128); +&alg_cbc_decrypt_implement("cmll",256); + +if ($::evp) { + &alg_ctr32_implement("cmll",128); + &alg_ctr32_implement("cmll",256); +} +}}} + +if (!$::evp) { +$code.=<<___; +.global Camellia_encrypt +Camellia_encrypt=cmll_t4_encrypt +.global Camellia_decrypt +Camellia_decrypt=cmll_t4_decrypt +.global Camellia_set_key +.align 32 +Camellia_set_key: + andcc %o2, 7, %g0 ! double-check alignment + bnz,a,pn %icc, 1f + mov -1, %o0 + brz,a,pn %o0, 1f + mov -1, %o0 + brz,a,pn %o2, 1f + mov -1, %o0 + andncc %o1, 0x1c0, %g0 + bnz,a,pn %icc, 1f + mov -2, %o0 + cmp %o1, 128 + bl,a,pn %icc, 1f + mov -2, %o0 + b cmll_t4_set_key + nop +1: retl + nop +.type Camellia_set_key,#function +.size Camellia_set_key,.-Camellia_set_key +___ + +my ($inp,$out,$len,$key,$ivec,$enc)=map("%o$_",(0..5)); + +$code.=<<___; +.globl Camellia_cbc_encrypt +.align 32 +Camellia_cbc_encrypt: + ld [$key + 272], %g1 + nop + brz $enc, .Lcbc_decrypt + cmp %g1, 3 + + be,pt %icc, cmll128_t4_cbc_encrypt + nop + ba cmll256_t4_cbc_encrypt + nop + +.Lcbc_decrypt: + be,pt %icc, cmll128_t4_cbc_decrypt + nop + ba cmll256_t4_cbc_decrypt + nop +.type Camellia_cbc_encrypt,#function +.size Camellia_cbc_encrypt,.-Camellia_cbc_encrypt +___ +} + +&emit_assembler(); + +close STDOUT; diff --git a/crypto/evp/e_camellia.c b/crypto/evp/e_camellia.c index 365d397164..da9dca35e4 100644 --- a/crypto/evp/e_camellia.c +++ b/crypto/evp/e_camellia.c @@ -61,6 +61,7 @@ #include #include #include "evp_locl.h" +#include "modes_lcl.h" static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); @@ -69,49 +70,110 @@ static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, typedef struct { CAMELLIA_KEY ks; + block128_f block; + union { + cbc128_f cbc; + ctr128_f ctr; + } stream; } EVP_CAMELLIA_KEY; +#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4)) + /* Attribute operation for Camellia */ #define data(ctx) EVP_C_DATA(EVP_CAMELLIA_KEY,ctx) -IMPLEMENT_BLOCK_CIPHER(camellia_128, ks, Camellia, EVP_CAMELLIA_KEY, - NID_camellia_128, 16, 16, 16, 128, - 0, camellia_init_key, NULL, - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL) -IMPLEMENT_BLOCK_CIPHER(camellia_192, ks, Camellia, EVP_CAMELLIA_KEY, - NID_camellia_192, 16, 24, 16, 128, - 0, camellia_init_key, NULL, - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL) -IMPLEMENT_BLOCK_CIPHER(camellia_256, ks, Camellia, EVP_CAMELLIA_KEY, - NID_camellia_256, 16, 32, 16, 128, - 0, camellia_init_key, NULL, - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL) +#if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) +/* ---------^^^ this is not a typo, just a way to detect that + * assembler support was in general requested... */ +#include "sparc_arch.h" -#define IMPLEMENT_CAMELLIA_CFBR(ksize,cbits) IMPLEMENT_CFBR(camellia,Camellia,EVP_CAMELLIA_KEY,ks,ksize,cbits,16,0) +extern unsigned int OPENSSL_sparcv9cap_P[]; -IMPLEMENT_CAMELLIA_CFBR(128,1) -IMPLEMENT_CAMELLIA_CFBR(192,1) -IMPLEMENT_CAMELLIA_CFBR(256,1) +#define SPARC_CMLL_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA) -IMPLEMENT_CAMELLIA_CFBR(128,8) -IMPLEMENT_CAMELLIA_CFBR(192,8) -IMPLEMENT_CAMELLIA_CFBR(256,8) +void cmll_t4_set_key (const unsigned char *key, int bits, + CAMELLIA_KEY *ks); +void cmll_t4_encrypt (const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void cmll_t4_decrypt (const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void cmll128_t4_cbc_encrypt (const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll128_t4_cbc_decrypt (const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll256_t4_cbc_encrypt (const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll256_t4_cbc_decrypt (const unsigned char *in, unsigned char *out, + size_t len, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll128_t4_ctr32_encrypt (const unsigned char *in, unsigned char *out, + size_t blocks, const CAMELLIA_KEY *key, + unsigned char *ivec); +void cmll256_t4_ctr32_encrypt (const unsigned char *in, unsigned char *out, + size_t blocks, const CAMELLIA_KEY *key, + unsigned char *ivec); - -/* The subkey for Camellia is generated. */ -static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) +static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) { - int ret; + int ret, mode, bits; + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; - ret=Camellia_set_key(key, ctx->key_len * 8, ctx->cipher_data); + mode = ctx->cipher->flags & EVP_CIPH_MODE; + bits = ctx->key_len*8; + + cmll_t4_set_key(key, bits, &dat->ks); + + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) + { + ret = 0; + dat->block = (block128_f)cmll_t4_decrypt; + switch (bits) { + case 128: + dat->stream.cbc = mode==EVP_CIPH_CBC_MODE ? + (cbc128_f)cmll128_t4_cbc_decrypt : + NULL; + break; + case 192: + case 256: + dat->stream.cbc = mode==EVP_CIPH_CBC_MODE ? + (cbc128_f)cmll256_t4_cbc_decrypt : + NULL; + break; + default: + ret = -1; + } + } + else { + ret = 0; + dat->block = (block128_f)cmll_t4_encrypt; + switch (bits) { + case 128: + if (mode==EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)cmll128_t4_cbc_encrypt; + else if (mode==EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)cmll128_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 192: + case 256: + if (mode==EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)cmll256_t4_cbc_encrypt; + else if (mode==EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)cmll256_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + default: + ret = -1; + } + } if(ret < 0) { @@ -122,6 +184,220 @@ static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, return 1; } +#define cmll_t4_cbc_cipher camellia_cbc_cipher +static int cmll_t4_cbc_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in, size_t len); + +#define cmll_t4_ecb_cipher camellia_ecb_cipher +static int cmll_t4_ecb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in, size_t len); + +#define cmll_t4_ofb_cipher camellia_ofb_cipher +static int cmll_t4_ofb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len); + +#define cmll_t4_cfb_cipher camellia_cfb_cipher +static int cmll_t4_cfb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len); + +#define cmll_t4_cfb8_cipher camellia_cfb8_cipher +static int cmll_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len); + +#define cmll_t4_cfb1_cipher camellia_cfb1_cipher +static int cmll_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len); + +#define cmll_t4_ctr_cipher camellia_ctr_cipher +static int cmll_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +#define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER cmll_t4_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + cmll_t4_init_key, \ + cmll_t4_##mode##_cipher, \ + NULL, \ + sizeof(EVP_CAMELLIA_KEY), \ + NULL,NULL,NULL,NULL }; \ +static const EVP_CIPHER camellia_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize, \ + keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + camellia_init_key, \ + camellia_##mode##_cipher, \ + NULL, \ + sizeof(EVP_CAMELLIA_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ +{ return SPARC_CMLL_CAPABLE?&cmll_t4_##keylen##_##mode:&camellia_##keylen##_##mode; } + +#else + +#define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER camellia_##keylen##_##mode = { \ + nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + camellia_init_key, \ + camellia_##mode##_cipher, \ + NULL, \ + sizeof(EVP_CAMELLIA_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ +{ return &camellia_##keylen##_##mode; } + +#endif + +#define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \ + BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \ + BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags) +#if 0 + BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags) +#endif + +/* The subkey for Camellia is generated. */ +static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + int ret, mode; + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + ret=Camellia_set_key(key, ctx->key_len * 8, &dat->ks); + if(ret < 0) + { + EVPerr(EVP_F_CAMELLIA_INIT_KEY,EVP_R_CAMELLIA_KEY_SETUP_FAILED); + return 0; + } + + mode = ctx->cipher->flags & EVP_CIPH_MODE; + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) + { + dat->block = (block128_f)Camellia_decrypt; + dat->stream.cbc = mode==EVP_CIPH_CBC_MODE ? + (cbc128_f)Camellia_cbc_encrypt : + NULL; + } + else + { + dat->block = (block128_f)Camellia_encrypt; + dat->stream.cbc = mode==EVP_CIPH_CBC_MODE ? + (cbc128_f)Camellia_cbc_encrypt : + NULL; + } + + + return 1; + } + +static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + if (dat->stream.cbc) + (*dat->stream.cbc)(in,out,len,&dat->ks,ctx->iv,ctx->encrypt); + else if (ctx->encrypt) + CRYPTO_cbc128_encrypt(in,out,len,&dat->ks,ctx->iv,dat->block); + else + CRYPTO_cbc128_encrypt(in,out,len,&dat->ks,ctx->iv,dat->block); + + return 1; +} + +static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t bl = ctx->cipher->block_size; + size_t i; + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + if (lenblock)(in+i,out+i,&dat->ks); + + return 1; +} + +static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len) +{ + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + CRYPTO_ofb128_encrypt(in,out,len,&dat->ks, + ctx->iv,&ctx->num,dat->block); + return 1; +} + +static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len) +{ + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + CRYPTO_cfb128_encrypt(in,out,len,&dat->ks, + ctx->iv,&ctx->num,ctx->encrypt,dat->block); + return 1; +} + +static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len) +{ + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + CRYPTO_cfb128_8_encrypt(in,out,len,&dat->ks, + ctx->iv,&ctx->num,ctx->encrypt,dat->block); + return 1; +} + +static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, + const unsigned char *in,size_t len) +{ + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + if (ctx->flags&EVP_CIPH_FLAG_LENGTH_BITS) { + CRYPTO_cfb128_1_encrypt(in,out,len,&dat->ks, + ctx->iv,&ctx->num,ctx->encrypt,dat->block); + return 1; + } + + while (len>=MAXBITCHUNK) { + CRYPTO_cfb128_1_encrypt(in,out,MAXBITCHUNK*8,&dat->ks, + ctx->iv,&ctx->num,ctx->encrypt,dat->block); + len-=MAXBITCHUNK; + } + if (len) + CRYPTO_cfb128_1_encrypt(in,out,len*8,&dat->ks, + ctx->iv,&ctx->num,ctx->encrypt,dat->block); + + return 1; +} + +static int camellia_ctr_cipher (EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = ctx->num; + EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *)ctx->cipher_data; + + if (dat->stream.ctr) + CRYPTO_ctr128_encrypt_ctr32(in,out,len,&dat->ks, + ctx->iv,ctx->buf,&num,dat->stream.ctr); + else + CRYPTO_ctr128_encrypt(in,out,len,&dat->ks, + ctx->iv,ctx->buf,&num,dat->block); + ctx->num = (size_t)num; + return 1; +} + +BLOCK_CIPHER_generic_pack(NID_camellia,128,EVP_CIPH_FLAG_FIPS) +BLOCK_CIPHER_generic_pack(NID_camellia,192,EVP_CIPH_FLAG_FIPS) +BLOCK_CIPHER_generic_pack(NID_camellia,256,EVP_CIPH_FLAG_FIPS) + #else # ifdef PEDANTIC