1073 lines
24 KiB
ArmAsm
1073 lines
24 KiB
ArmAsm
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
|
|
// Use of this source code is governed by a license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// +build amd64,!gccgo,!appengine,!nacl
|
|
|
|
#include "const.s"
|
|
#include "macro.s"
|
|
|
|
// FINALIZE xors len bytes from src and block using
|
|
// the temp. registers t0 and t1 and writes the result
|
|
// to dst.
|
|
#define FINALIZE(dst, src, block, len, t0, t1) \
|
|
XORQ t0, t0; \
|
|
XORQ t1, t1; \
|
|
FINALIZE_LOOP:; \
|
|
MOVB 0(src), t0; \
|
|
MOVB 0(block), t1; \
|
|
XORQ t0, t1; \
|
|
MOVB t1, 0(dst); \
|
|
INCQ src; \
|
|
INCQ block; \
|
|
INCQ dst; \
|
|
DECQ len; \
|
|
JG FINALIZE_LOOP \
|
|
|
|
#define Dst DI
|
|
#define Nonce AX
|
|
#define Key BX
|
|
#define Rounds DX
|
|
|
|
// func initialize(state *[64]byte, key []byte, nonce *[16]byte)
|
|
TEXT ·initialize(SB), 4, $0-40
|
|
MOVQ state+0(FP), Dst
|
|
MOVQ key+8(FP), Key
|
|
MOVQ nonce+32(FP), Nonce
|
|
|
|
MOVOU ·sigma<>(SB), X0
|
|
MOVOU 0*16(Key), X1
|
|
MOVOU 1*16(Key), X2
|
|
MOVOU 0*16(Nonce), X3
|
|
|
|
MOVOU X0, 0*16(Dst)
|
|
MOVOU X1, 1*16(Dst)
|
|
MOVOU X2, 2*16(Dst)
|
|
MOVOU X3, 3*16(Dst)
|
|
RET
|
|
|
|
// func hChaCha20AVX(out *[32]byte, nonce *[16]byte, key *[32]byte)
|
|
TEXT ·hChaCha20AVX(SB), 4, $0-24
|
|
MOVQ out+0(FP), Dst
|
|
MOVQ nonce+8(FP), Nonce
|
|
MOVQ key+16(FP), Key
|
|
|
|
VMOVDQU ·sigma<>(SB), X0
|
|
VMOVDQU 0*16(Key), X1
|
|
VMOVDQU 1*16(Key), X2
|
|
VMOVDQU 0*16(Nonce), X3
|
|
VMOVDQU ·rol16_AVX2<>(SB), X5
|
|
VMOVDQU ·rol8_AVX2<>(SB), X6
|
|
MOVQ $20, Rounds
|
|
|
|
CHACHA_LOOP:
|
|
CHACHA_QROUND_AVX(X0, X1, X2, X3, X4, X5, X6)
|
|
CHACHA_SHUFFLE_AVX(X1, X2, X3)
|
|
CHACHA_QROUND_AVX(X0, X1, X2, X3, X4, X5, X6)
|
|
CHACHA_SHUFFLE_AVX(X3, X2, X1)
|
|
SUBQ $2, Rounds
|
|
JNZ CHACHA_LOOP
|
|
|
|
VMOVDQU X0, 0*16(Dst)
|
|
VMOVDQU X3, 1*16(Dst)
|
|
VZEROUPPER
|
|
RET
|
|
|
|
// func hChaCha20SSE2(out *[32]byte, nonce *[16]byte, key *[32]byte)
|
|
TEXT ·hChaCha20SSE2(SB), 4, $0-24
|
|
MOVQ out+0(FP), Dst
|
|
MOVQ nonce+8(FP), Nonce
|
|
MOVQ key+16(FP), Key
|
|
|
|
MOVOU ·sigma<>(SB), X0
|
|
MOVOU 0*16(Key), X1
|
|
MOVOU 1*16(Key), X2
|
|
MOVOU 0*16(Nonce), X3
|
|
MOVQ $20, Rounds
|
|
|
|
CHACHA_LOOP:
|
|
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
|
CHACHA_SHUFFLE_SSE(X1, X2, X3)
|
|
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
|
CHACHA_SHUFFLE_SSE(X3, X2, X1)
|
|
SUBQ $2, Rounds
|
|
JNZ CHACHA_LOOP
|
|
|
|
MOVOU X0, 0*16(Dst)
|
|
MOVOU X3, 1*16(Dst)
|
|
RET
|
|
|
|
// func hChaCha20SSSE3(out *[32]byte, nonce *[16]byte, key *[32]byte)
|
|
TEXT ·hChaCha20SSSE3(SB), 4, $0-24
|
|
MOVQ out+0(FP), Dst
|
|
MOVQ nonce+8(FP), Nonce
|
|
MOVQ key+16(FP), Key
|
|
|
|
MOVOU ·sigma<>(SB), X0
|
|
MOVOU 0*16(Key), X1
|
|
MOVOU 1*16(Key), X2
|
|
MOVOU 0*16(Nonce), X3
|
|
MOVOU ·rol16<>(SB), X5
|
|
MOVOU ·rol8<>(SB), X6
|
|
MOVQ $20, Rounds
|
|
|
|
chacha_loop:
|
|
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
|
|
CHACHA_SHUFFLE_SSE(X1, X2, X3)
|
|
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
|
|
CHACHA_SHUFFLE_SSE(X3, X2, X1)
|
|
SUBQ $2, Rounds
|
|
JNZ chacha_loop
|
|
|
|
MOVOU X0, 0*16(Dst)
|
|
MOVOU X3, 1*16(Dst)
|
|
RET
|
|
|
|
#undef Dst
|
|
#undef Nonce
|
|
#undef Key
|
|
#undef Rounds
|
|
|
|
#define Dst DI
|
|
#define Src SI
|
|
#define Len R12
|
|
#define Rounds DX
|
|
#define Buffer BX
|
|
#define State AX
|
|
#define Stack SP
|
|
#define SavedSP R8
|
|
#define Tmp0 R9
|
|
#define Tmp1 R10
|
|
#define Tmp2 R11
|
|
|
|
// func xorKeyStreamSSE2(dst, src []byte, block, state *[64]byte, rounds int) int
|
|
TEXT ·xorKeyStreamSSE2(SB), 4, $112-80
|
|
MOVQ dst_base+0(FP), Dst
|
|
MOVQ src_base+24(FP), Src
|
|
MOVQ block+48(FP), Buffer
|
|
MOVQ state+56(FP), State
|
|
MOVQ rounds+64(FP), Rounds
|
|
MOVQ src_len+32(FP), Len
|
|
|
|
MOVOU 0*16(State), X0
|
|
MOVOU 1*16(State), X1
|
|
MOVOU 2*16(State), X2
|
|
MOVOU 3*16(State), X3
|
|
|
|
MOVQ Stack, SavedSP
|
|
ADDQ $16, Stack
|
|
ANDQ $-16, Stack
|
|
|
|
TESTQ Len, Len
|
|
JZ DONE
|
|
|
|
MOVOU ·one<>(SB), X4
|
|
MOVO X0, 0*16(Stack)
|
|
MOVO X1, 1*16(Stack)
|
|
MOVO X2, 2*16(Stack)
|
|
MOVO X3, 3*16(Stack)
|
|
MOVO X4, 4*16(Stack)
|
|
|
|
CMPQ Len, $64
|
|
JLE GENERATE_KEYSTREAM_64
|
|
CMPQ Len, $128
|
|
JLE GENERATE_KEYSTREAM_128
|
|
CMPQ Len, $192
|
|
JLE GENERATE_KEYSTREAM_192
|
|
|
|
GENERATE_KEYSTREAM_256:
|
|
MOVO X0, X12
|
|
MOVO X1, X13
|
|
MOVO X2, X14
|
|
MOVO X3, X15
|
|
PADDQ 4*16(Stack), X15
|
|
MOVO X0, X8
|
|
MOVO X1, X9
|
|
MOVO X2, X10
|
|
MOVO X15, X11
|
|
PADDQ 4*16(Stack), X11
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X11, X7
|
|
PADDQ 4*16(Stack), X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
MOVO X3, 3*16(Stack) // Save X3
|
|
|
|
CHACHA_LOOP_256:
|
|
MOVO X4, 5*16(Stack)
|
|
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
|
CHACHA_QROUND_SSE2(X12, X13, X14, X15, X4)
|
|
MOVO 5*16(Stack), X4
|
|
MOVO X0, 5*16(Stack)
|
|
CHACHA_QROUND_SSE2(X8, X9, X10, X11, X0)
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
|
MOVO 5*16(Stack), X0
|
|
CHACHA_SHUFFLE_SSE(X1, X2, X3)
|
|
CHACHA_SHUFFLE_SSE(X13, X14, X15)
|
|
CHACHA_SHUFFLE_SSE(X9, X10, X11)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
MOVO X4, 5*16(Stack)
|
|
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
|
|
CHACHA_QROUND_SSE2(X12, X13, X14, X15, X4)
|
|
MOVO 5*16(Stack), X4
|
|
MOVO X0, 5*16(Stack)
|
|
CHACHA_QROUND_SSE2(X8, X9, X10, X11, X0)
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
|
MOVO 5*16(Stack), X0
|
|
CHACHA_SHUFFLE_SSE(X3, X2, X1)
|
|
CHACHA_SHUFFLE_SSE(X15, X14, X13)
|
|
CHACHA_SHUFFLE_SSE(X11, X10, X9)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_256
|
|
|
|
PADDL 0*16(Stack), X0
|
|
PADDL 1*16(Stack), X1
|
|
PADDL 2*16(Stack), X2
|
|
PADDL 3*16(Stack), X3
|
|
MOVO X4, 5*16(Stack) // Save X4
|
|
XOR_SSE(Dst, Src, 0, X0, X1, X2, X3, X4)
|
|
MOVO 5*16(Stack), X4 // Restore X4
|
|
|
|
MOVO 0*16(Stack), X0
|
|
MOVO 1*16(Stack), X1
|
|
MOVO 2*16(Stack), X2
|
|
MOVO 3*16(Stack), X3
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
PADDL X0, X12
|
|
PADDL X1, X13
|
|
PADDL X2, X14
|
|
PADDL X3, X15
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X8
|
|
PADDL X1, X9
|
|
PADDL X2, X10
|
|
PADDL X3, X11
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
XOR_SSE(Dst, Src, 64, X12, X13, X14, X15, X0)
|
|
XOR_SSE(Dst, Src, 128, X8, X9, X10, X11, X0)
|
|
MOVO 0*16(Stack), X0 // Restore X0
|
|
ADDQ $192, Dst
|
|
ADDQ $192, Src
|
|
SUBQ $192, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE
|
|
CMPQ Len, $64 // If Len <= 64 -> gen. only 64 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_64
|
|
CMPQ Len, $128 // If 64 < Len <= 128 -> gen. only 128 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_128
|
|
CMPQ Len, $192 // If Len > 192 -> repeat, otherwise Len > 128 && Len <= 192 -> gen. 192 byte keystream
|
|
JG GENERATE_KEYSTREAM_256
|
|
|
|
GENERATE_KEYSTREAM_192:
|
|
MOVO X0, X12
|
|
MOVO X1, X13
|
|
MOVO X2, X14
|
|
MOVO X3, X15
|
|
MOVO X0, X8
|
|
MOVO X1, X9
|
|
MOVO X2, X10
|
|
MOVO X3, X11
|
|
PADDQ 4*16(Stack), X11
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X11, X7
|
|
PADDQ 4*16(Stack), X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
CHACHA_LOOP_192:
|
|
CHACHA_QROUND_SSE2(X12, X13, X14, X15, X0)
|
|
CHACHA_QROUND_SSE2(X8, X9, X10, X11, X0)
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
|
CHACHA_SHUFFLE_SSE(X13, X14, X15)
|
|
CHACHA_SHUFFLE_SSE(X9, X10, X11)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
CHACHA_QROUND_SSE2(X12, X13, X14, X15, X0)
|
|
CHACHA_QROUND_SSE2(X8, X9, X10, X11, X0)
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
|
|
CHACHA_SHUFFLE_SSE(X15, X14, X13)
|
|
CHACHA_SHUFFLE_SSE(X11, X10, X9)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_192
|
|
|
|
MOVO 0*16(Stack), X0 // Restore X0
|
|
PADDL X0, X12
|
|
PADDL X1, X13
|
|
PADDL X2, X14
|
|
PADDL X3, X15
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X8
|
|
PADDL X1, X9
|
|
PADDL X2, X10
|
|
PADDL X3, X11
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
XOR_SSE(Dst, Src, 0, X12, X13, X14, X15, X0)
|
|
XOR_SSE(Dst, Src, 64, X8, X9, X10, X11, X0)
|
|
MOVO 0*16(Stack), X0 // Restore X0
|
|
ADDQ $128, Dst
|
|
ADDQ $128, Src
|
|
SUBQ $128, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE
|
|
CMPQ Len, $64 // If Len <= 64 -> gen. only 64 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_64
|
|
|
|
GENERATE_KEYSTREAM_128:
|
|
MOVO X0, X8
|
|
MOVO X1, X9
|
|
MOVO X2, X10
|
|
MOVO X3, X11
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X3, X7
|
|
PADDQ 4*16(Stack), X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
CHACHA_LOOP_128:
|
|
CHACHA_QROUND_SSE2(X8, X9, X10, X11, X12)
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X12)
|
|
CHACHA_SHUFFLE_SSE(X9, X10, X11)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
CHACHA_QROUND_SSE2(X8, X9, X10, X11, X12)
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X12)
|
|
CHACHA_SHUFFLE_SSE(X11, X10, X9)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_128
|
|
|
|
PADDL X0, X8
|
|
PADDL X1, X9
|
|
PADDL X2, X10
|
|
PADDL X3, X11
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
XOR_SSE(Dst, Src, 0, X8, X9, X10, X11, X12)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE // If Len == 0 -> DONE, otherwise Len <= 64 -> gen 64 byte keystream
|
|
|
|
GENERATE_KEYSTREAM_64:
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X3, X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
CHACHA_LOOP_64:
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X8)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X8)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_64
|
|
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Src
|
|
ADDQ $64, Dst
|
|
SUBQ $64, Len
|
|
JMP DONE // jump directly to DONE - there is no keystream to buffer, Len == 0 always true.
|
|
|
|
BUFFER_KEYSTREAM:
|
|
MOVOU X4, 0*16(Buffer)
|
|
MOVOU X5, 1*16(Buffer)
|
|
MOVOU X6, 2*16(Buffer)
|
|
MOVOU X7, 3*16(Buffer)
|
|
MOVQ Len, Tmp0
|
|
FINALIZE(Dst, Src, Buffer, Tmp0, Tmp1, Tmp2)
|
|
|
|
DONE:
|
|
MOVQ SavedSP, Stack // Restore stack pointer
|
|
MOVOU X3, 3*16(State)
|
|
MOVQ Len, ret+72(FP)
|
|
RET
|
|
|
|
// func xorKeyStreamSSSE3(dst, src []byte, block, state *[64]byte, rounds int) int
|
|
TEXT ·xorKeyStreamSSSE3(SB), 4, $144-80
|
|
MOVQ dst_base+0(FP), Dst
|
|
MOVQ src_base+24(FP), Src
|
|
MOVQ block+48(FP), Buffer
|
|
MOVQ state+56(FP), State
|
|
MOVQ rounds+64(FP), Rounds
|
|
MOVQ src_len+32(FP), Len
|
|
|
|
MOVOU 0*16(State), X0
|
|
MOVOU 1*16(State), X1
|
|
MOVOU 2*16(State), X2
|
|
MOVOU 3*16(State), X3
|
|
|
|
MOVQ Stack, SavedSP
|
|
ADDQ $16, Stack
|
|
ANDQ $-16, Stack
|
|
|
|
TESTQ Len, Len
|
|
JZ DONE
|
|
|
|
MOVOU ·one<>(SB), X4
|
|
MOVOU ·rol16<>(SB), X5
|
|
MOVOU ·rol8<>(SB), X6
|
|
MOVO X0, 0*16(Stack)
|
|
MOVO X1, 1*16(Stack)
|
|
MOVO X2, 2*16(Stack)
|
|
MOVO X3, 3*16(Stack)
|
|
MOVO X4, 4*16(Stack)
|
|
MOVO X5, 6*16(Stack)
|
|
MOVO X6, 7*16(Stack)
|
|
|
|
CMPQ Len, $64
|
|
JLE GENERATE_KEYSTREAM_64
|
|
CMPQ Len, $128
|
|
JLE GENERATE_KEYSTREAM_128
|
|
CMPQ Len, $192
|
|
JLE GENERATE_KEYSTREAM_192
|
|
|
|
GENERATE_KEYSTREAM_256:
|
|
MOVO X0, X12
|
|
MOVO X1, X13
|
|
MOVO X2, X14
|
|
MOVO X3, X15
|
|
PADDQ 4*16(Stack), X15
|
|
MOVO X0, X8
|
|
MOVO X1, X9
|
|
MOVO X2, X10
|
|
MOVO X15, X11
|
|
PADDQ 4*16(Stack), X11
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X11, X7
|
|
PADDQ 4*16(Stack), X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
MOVO X3, 3*16(Stack) // Save X3
|
|
|
|
CHACHA_LOOP_256:
|
|
MOVO X4, 5*16(Stack)
|
|
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_SSSE3(X12, X13, X14, X15, X4, 6*16(Stack), 7*16(Stack))
|
|
MOVO 5*16(Stack), X4
|
|
MOVO X0, 5*16(Stack)
|
|
CHACHA_QROUND_SSSE3(X8, X9, X10, X11, X0, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, 6*16(Stack), 7*16(Stack))
|
|
MOVO 5*16(Stack), X0
|
|
CHACHA_SHUFFLE_SSE(X1, X2, X3)
|
|
CHACHA_SHUFFLE_SSE(X13, X14, X15)
|
|
CHACHA_SHUFFLE_SSE(X9, X10, X11)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
MOVO X4, 5*16(Stack)
|
|
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_SSSE3(X12, X13, X14, X15, X4, 6*16(Stack), 7*16(Stack))
|
|
MOVO 5*16(Stack), X4
|
|
MOVO X0, 5*16(Stack)
|
|
CHACHA_QROUND_SSSE3(X8, X9, X10, X11, X0, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, 6*16(Stack), 7*16(Stack))
|
|
MOVO 5*16(Stack), X0
|
|
CHACHA_SHUFFLE_SSE(X3, X2, X1)
|
|
CHACHA_SHUFFLE_SSE(X15, X14, X13)
|
|
CHACHA_SHUFFLE_SSE(X11, X10, X9)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_256
|
|
|
|
PADDL 0*16(Stack), X0
|
|
PADDL 1*16(Stack), X1
|
|
PADDL 2*16(Stack), X2
|
|
PADDL 3*16(Stack), X3
|
|
MOVO X4, 5*16(Stack) // Save X4
|
|
XOR_SSE(Dst, Src, 0, X0, X1, X2, X3, X4)
|
|
MOVO 5*16(Stack), X4 // Restore X4
|
|
|
|
MOVO 0*16(Stack), X0
|
|
MOVO 1*16(Stack), X1
|
|
MOVO 2*16(Stack), X2
|
|
MOVO 3*16(Stack), X3
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
PADDL X0, X12
|
|
PADDL X1, X13
|
|
PADDL X2, X14
|
|
PADDL X3, X15
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X8
|
|
PADDL X1, X9
|
|
PADDL X2, X10
|
|
PADDL X3, X11
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
XOR_SSE(Dst, Src, 64, X12, X13, X14, X15, X0)
|
|
XOR_SSE(Dst, Src, 128, X8, X9, X10, X11, X0)
|
|
MOVO 0*16(Stack), X0 // Restore X0
|
|
ADDQ $192, Dst
|
|
ADDQ $192, Src
|
|
SUBQ $192, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE
|
|
CMPQ Len, $64 // If Len <= 64 -> gen. only 64 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_64
|
|
CMPQ Len, $128 // If 64 < Len <= 128 -> gen. only 128 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_128
|
|
CMPQ Len, $192 // If Len > 192 -> repeat, otherwise Len > 128 && Len <= 192 -> gen. 192 byte keystream
|
|
JG GENERATE_KEYSTREAM_256
|
|
|
|
GENERATE_KEYSTREAM_192:
|
|
MOVO X0, X12
|
|
MOVO X1, X13
|
|
MOVO X2, X14
|
|
MOVO X3, X15
|
|
MOVO X0, X8
|
|
MOVO X1, X9
|
|
MOVO X2, X10
|
|
MOVO X3, X11
|
|
PADDQ 4*16(Stack), X11
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X11, X7
|
|
PADDQ 4*16(Stack), X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
MOVO 6*16(Stack), X1 // Load 16 bit rotate-left constant
|
|
MOVO 7*16(Stack), X2 // Load 8 bit rotate-left constant
|
|
|
|
CHACHA_LOOP_192:
|
|
CHACHA_QROUND_SSSE3(X12, X13, X14, X15, X0, X1, X2)
|
|
CHACHA_QROUND_SSSE3(X8, X9, X10, X11, X0, X1, X2)
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, X1, X2)
|
|
CHACHA_SHUFFLE_SSE(X13, X14, X15)
|
|
CHACHA_SHUFFLE_SSE(X9, X10, X11)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
CHACHA_QROUND_SSSE3(X12, X13, X14, X15, X0, X1, X2)
|
|
CHACHA_QROUND_SSSE3(X8, X9, X10, X11, X0, X1, X2)
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X0, X1, X2)
|
|
CHACHA_SHUFFLE_SSE(X15, X14, X13)
|
|
CHACHA_SHUFFLE_SSE(X11, X10, X9)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_192
|
|
|
|
MOVO 0*16(Stack), X0 // Restore X0
|
|
MOVO 1*16(Stack), X1 // Restore X1
|
|
MOVO 2*16(Stack), X2 // Restore X2
|
|
PADDL X0, X12
|
|
PADDL X1, X13
|
|
PADDL X2, X14
|
|
PADDL X3, X15
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X8
|
|
PADDL X1, X9
|
|
PADDL X2, X10
|
|
PADDL X3, X11
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
XOR_SSE(Dst, Src, 0, X12, X13, X14, X15, X0)
|
|
XOR_SSE(Dst, Src, 64, X8, X9, X10, X11, X0)
|
|
MOVO 0*16(Stack), X0 // Restore X0
|
|
ADDQ $128, Dst
|
|
ADDQ $128, Src
|
|
SUBQ $128, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE
|
|
CMPQ Len, $64 // If Len <= 64 -> gen. only 64 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_64
|
|
|
|
GENERATE_KEYSTREAM_128:
|
|
MOVO X0, X8
|
|
MOVO X1, X9
|
|
MOVO X2, X10
|
|
MOVO X3, X11
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X3, X7
|
|
PADDQ 4*16(Stack), X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
MOVO 6*16(Stack), X13 // Load 16 bit rotate-left constant
|
|
MOVO 7*16(Stack), X14 // Load 8 bit rotate-left constant
|
|
|
|
CHACHA_LOOP_128:
|
|
CHACHA_QROUND_SSSE3(X8, X9, X10, X11, X12, X13, X14)
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X12, X13, X14)
|
|
CHACHA_SHUFFLE_SSE(X9, X10, X11)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
CHACHA_QROUND_SSSE3(X8, X9, X10, X11, X12, X13, X14)
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X12, X13, X14)
|
|
CHACHA_SHUFFLE_SSE(X11, X10, X9)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_128
|
|
|
|
PADDL X0, X8
|
|
PADDL X1, X9
|
|
PADDL X2, X10
|
|
PADDL X3, X11
|
|
PADDQ 4*16(Stack), X3
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
XOR_SSE(Dst, Src, 0, X8, X9, X10, X11, X12)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE // If Len == 0 -> DONE, otherwise Len <= 64 -> gen 64 byte keystream
|
|
|
|
GENERATE_KEYSTREAM_64:
|
|
MOVO X0, X4
|
|
MOVO X1, X5
|
|
MOVO X2, X6
|
|
MOVO X3, X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
MOVO 6*16(Stack), X9 // Load 16 bit rotate-left constant
|
|
MOVO 7*16(Stack), X10 // Load 8 bit rotate-left constant
|
|
|
|
CHACHA_LOOP_64:
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10)
|
|
CHACHA_SHUFFLE_SSE(X5, X6, X7)
|
|
CHACHA_QROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10)
|
|
CHACHA_SHUFFLE_SSE(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_64
|
|
|
|
PADDL X0, X4
|
|
PADDL X1, X5
|
|
PADDL X2, X6
|
|
PADDL X3, X7
|
|
PADDQ 4*16(Stack), X3
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Src
|
|
ADDQ $64, Dst
|
|
SUBQ $64, Len
|
|
JMP DONE // jump directly to DONE - there is no keystream to buffer, Len == 0 always true.
|
|
|
|
BUFFER_KEYSTREAM:
|
|
MOVOU X4, 0*16(Buffer)
|
|
MOVOU X5, 1*16(Buffer)
|
|
MOVOU X6, 2*16(Buffer)
|
|
MOVOU X7, 3*16(Buffer)
|
|
MOVQ Len, Tmp0
|
|
FINALIZE(Dst, Src, Buffer, Tmp0, Tmp1, Tmp2)
|
|
|
|
DONE:
|
|
MOVQ SavedSP, Stack // Restore stack pointer
|
|
MOVOU X3, 3*16(State)
|
|
MOVQ Len, ret+72(FP)
|
|
RET
|
|
|
|
// func xorKeyStreamAVX(dst, src []byte, block, state *[64]byte, rounds int) int
|
|
TEXT ·xorKeyStreamAVX(SB), 4, $144-80
|
|
MOVQ dst_base+0(FP), Dst
|
|
MOVQ src_base+24(FP), Src
|
|
MOVQ block+48(FP), Buffer
|
|
MOVQ state+56(FP), State
|
|
MOVQ rounds+64(FP), Rounds
|
|
MOVQ src_len+32(FP), Len
|
|
|
|
VMOVDQU 0*16(State), X0
|
|
VMOVDQU 1*16(State), X1
|
|
VMOVDQU 2*16(State), X2
|
|
VMOVDQU 3*16(State), X3
|
|
|
|
MOVQ Stack, SavedSP
|
|
ADDQ $16, Stack
|
|
ANDQ $-16, Stack
|
|
|
|
TESTQ Len, Len
|
|
JZ DONE
|
|
|
|
VMOVDQU ·one<>(SB), X4
|
|
VMOVDQU ·rol16<>(SB), X5
|
|
VMOVDQU ·rol8<>(SB), X6
|
|
VMOVDQA X0, 0*16(Stack)
|
|
VMOVDQA X1, 1*16(Stack)
|
|
VMOVDQA X2, 2*16(Stack)
|
|
VMOVDQA X3, 3*16(Stack)
|
|
VMOVDQA X4, 4*16(Stack)
|
|
VMOVDQA X5, 6*16(Stack)
|
|
VMOVDQA X6, 7*16(Stack)
|
|
|
|
CMPQ Len, $64
|
|
JLE GENERATE_KEYSTREAM_64
|
|
CMPQ Len, $128
|
|
JLE GENERATE_KEYSTREAM_128
|
|
CMPQ Len, $192
|
|
JLE GENERATE_KEYSTREAM_192
|
|
|
|
GENERATE_KEYSTREAM_256:
|
|
VMOVDQA X0, X12
|
|
VMOVDQA X1, X13
|
|
VMOVDQA X2, X14
|
|
VMOVDQA X3, X15
|
|
VPADDQ 4*16(Stack), X15, X15
|
|
VMOVDQA X0, X8
|
|
VMOVDQA X1, X9
|
|
VMOVDQA X2, X10
|
|
VMOVDQA X15, X11
|
|
VPADDQ 4*16(Stack), X11, X11
|
|
VMOVDQA X0, X4
|
|
VMOVDQA X1, X5
|
|
VMOVDQA X2, X6
|
|
VMOVDQA X11, X7
|
|
VPADDQ 4*16(Stack), X7, X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
VMOVDQA X3, 3*16(Stack) // Save X3
|
|
|
|
CHACHA_LOOP_256:
|
|
VMOVDQA X4, 5*16(Stack)
|
|
CHACHA_QROUND_AVX(X0, X1, X2, X3, X4, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_AVX(X12, X13, X14, X15, X4, 6*16(Stack), 7*16(Stack))
|
|
VMOVDQA 5*16(Stack), X4
|
|
VMOVDQA X0, 5*16(Stack)
|
|
CHACHA_QROUND_AVX(X8, X9, X10, X11, X0, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X0, 6*16(Stack), 7*16(Stack))
|
|
VMOVDQA 5*16(Stack), X0
|
|
CHACHA_SHUFFLE_AVX(X1, X2, X3)
|
|
CHACHA_SHUFFLE_AVX(X13, X14, X15)
|
|
CHACHA_SHUFFLE_AVX(X9, X10, X11)
|
|
CHACHA_SHUFFLE_AVX(X5, X6, X7)
|
|
VMOVDQA X4, 5*16(Stack)
|
|
CHACHA_QROUND_AVX(X0, X1, X2, X3, X4, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_AVX(X12, X13, X14, X15, X4, 6*16(Stack), 7*16(Stack))
|
|
VMOVDQA 5*16(Stack), X4
|
|
VMOVDQA X0, 5*16(Stack)
|
|
CHACHA_QROUND_AVX(X8, X9, X10, X11, X0, 6*16(Stack), 7*16(Stack))
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X0, 6*16(Stack), 7*16(Stack))
|
|
VMOVDQA 5*16(Stack), X0
|
|
CHACHA_SHUFFLE_AVX(X3, X2, X1)
|
|
CHACHA_SHUFFLE_AVX(X15, X14, X13)
|
|
CHACHA_SHUFFLE_AVX(X11, X10, X9)
|
|
CHACHA_SHUFFLE_AVX(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_256
|
|
|
|
VPADDD 0*16(Stack), X0, X0
|
|
VPADDD 1*16(Stack), X1, X1
|
|
VPADDD 2*16(Stack), X2, X2
|
|
VPADDD 3*16(Stack), X3, X3
|
|
VMOVDQA X4, 5*16(Stack) // Save X4
|
|
XOR_AVX(Dst, Src, 0, X0, X1, X2, X3, X4)
|
|
VMOVDQA 5*16(Stack), X4 // Restore X4
|
|
|
|
VMOVDQA 0*16(Stack), X0
|
|
VMOVDQA 1*16(Stack), X1
|
|
VMOVDQA 2*16(Stack), X2
|
|
VMOVDQA 3*16(Stack), X3
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
|
|
VPADDD X0, X12, X12
|
|
VPADDD X1, X13, X13
|
|
VPADDD X2, X14, X14
|
|
VPADDD X3, X15, X15
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
VPADDD X0, X8, X8
|
|
VPADDD X1, X9, X9
|
|
VPADDD X2, X10, X10
|
|
VPADDD X3, X11, X11
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
VPADDD X0, X4, X4
|
|
VPADDD X1, X5, X5
|
|
VPADDD X2, X6, X6
|
|
VPADDD X3, X7, X7
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
|
|
XOR_AVX(Dst, Src, 64, X12, X13, X14, X15, X0)
|
|
XOR_AVX(Dst, Src, 128, X8, X9, X10, X11, X0)
|
|
VMOVDQA 0*16(Stack), X0 // Restore X0
|
|
ADDQ $192, Dst
|
|
ADDQ $192, Src
|
|
SUBQ $192, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_AVX(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE
|
|
CMPQ Len, $64 // If Len <= 64 -> gen. only 64 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_64
|
|
CMPQ Len, $128 // If 64 < Len <= 128 -> gen. only 128 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_128
|
|
CMPQ Len, $192 // If Len > 192 -> repeat, otherwise Len > 128 && Len <= 192 -> gen. 192 byte keystream
|
|
JG GENERATE_KEYSTREAM_256
|
|
|
|
GENERATE_KEYSTREAM_192:
|
|
VMOVDQA X0, X12
|
|
VMOVDQA X1, X13
|
|
VMOVDQA X2, X14
|
|
VMOVDQA X3, X15
|
|
VMOVDQA X0, X8
|
|
VMOVDQA X1, X9
|
|
VMOVDQA X2, X10
|
|
VMOVDQA X3, X11
|
|
VPADDQ 4*16(Stack), X11, X11
|
|
VMOVDQA X0, X4
|
|
VMOVDQA X1, X5
|
|
VMOVDQA X2, X6
|
|
VMOVDQA X11, X7
|
|
VPADDQ 4*16(Stack), X7, X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
VMOVDQA 6*16(Stack), X1 // Load 16 bit rotate-left constant
|
|
VMOVDQA 7*16(Stack), X2 // Load 8 bit rotate-left constant
|
|
|
|
CHACHA_LOOP_192:
|
|
CHACHA_QROUND_AVX(X12, X13, X14, X15, X0, X1, X2)
|
|
CHACHA_QROUND_AVX(X8, X9, X10, X11, X0, X1, X2)
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X0, X1, X2)
|
|
CHACHA_SHUFFLE_AVX(X13, X14, X15)
|
|
CHACHA_SHUFFLE_AVX(X9, X10, X11)
|
|
CHACHA_SHUFFLE_AVX(X5, X6, X7)
|
|
CHACHA_QROUND_AVX(X12, X13, X14, X15, X0, X1, X2)
|
|
CHACHA_QROUND_AVX(X8, X9, X10, X11, X0, X1, X2)
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X0, X1, X2)
|
|
CHACHA_SHUFFLE_AVX(X15, X14, X13)
|
|
CHACHA_SHUFFLE_AVX(X11, X10, X9)
|
|
CHACHA_SHUFFLE_AVX(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_192
|
|
|
|
VMOVDQA 0*16(Stack), X0 // Restore X0
|
|
VMOVDQA 1*16(Stack), X1 // Restore X1
|
|
VMOVDQA 2*16(Stack), X2 // Restore X2
|
|
VPADDD X0, X12, X12
|
|
VPADDD X1, X13, X13
|
|
VPADDD X2, X14, X14
|
|
VPADDD X3, X15, X15
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
VPADDD X0, X8, X8
|
|
VPADDD X1, X9, X9
|
|
VPADDD X2, X10, X10
|
|
VPADDD X3, X11, X11
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
VPADDD X0, X4, X4
|
|
VPADDD X1, X5, X5
|
|
VPADDD X2, X6, X6
|
|
VPADDD X3, X7, X7
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
|
|
XOR_AVX(Dst, Src, 0, X12, X13, X14, X15, X0)
|
|
XOR_AVX(Dst, Src, 64, X8, X9, X10, X11, X0)
|
|
VMOVDQA 0*16(Stack), X0 // Restore X0
|
|
ADDQ $128, Dst
|
|
ADDQ $128, Src
|
|
SUBQ $128, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_AVX(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE
|
|
CMPQ Len, $64 // If Len <= 64 -> gen. only 64 byte keystream.
|
|
JLE GENERATE_KEYSTREAM_64
|
|
|
|
GENERATE_KEYSTREAM_128:
|
|
VMOVDQA X0, X8
|
|
VMOVDQA X1, X9
|
|
VMOVDQA X2, X10
|
|
VMOVDQA X3, X11
|
|
VMOVDQA X0, X4
|
|
VMOVDQA X1, X5
|
|
VMOVDQA X2, X6
|
|
VMOVDQA X3, X7
|
|
VPADDQ 4*16(Stack), X7, X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
VMOVDQA 6*16(Stack), X13 // Load 16 bit rotate-left constant
|
|
VMOVDQA 7*16(Stack), X14 // Load 8 bit rotate-left constant
|
|
|
|
CHACHA_LOOP_128:
|
|
CHACHA_QROUND_AVX(X8, X9, X10, X11, X12, X13, X14)
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X12, X13, X14)
|
|
CHACHA_SHUFFLE_AVX(X9, X10, X11)
|
|
CHACHA_SHUFFLE_AVX(X5, X6, X7)
|
|
CHACHA_QROUND_AVX(X8, X9, X10, X11, X12, X13, X14)
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X12, X13, X14)
|
|
CHACHA_SHUFFLE_AVX(X11, X10, X9)
|
|
CHACHA_SHUFFLE_AVX(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_128
|
|
|
|
VPADDD X0, X8, X8
|
|
VPADDD X1, X9, X9
|
|
VPADDD X2, X10, X10
|
|
VPADDD X3, X11, X11
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
VPADDD X0, X4, X4
|
|
VPADDD X1, X5, X5
|
|
VPADDD X2, X6, X6
|
|
VPADDD X3, X7, X7
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
|
|
XOR_AVX(Dst, Src, 0, X8, X9, X10, X11, X12)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_AVX(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Dst
|
|
ADDQ $64, Src
|
|
SUBQ $64, Len
|
|
JZ DONE // If Len == 0 -> DONE, otherwise Len <= 64 -> gen 64 byte keystream
|
|
|
|
GENERATE_KEYSTREAM_64:
|
|
VMOVDQA X0, X4
|
|
VMOVDQA X1, X5
|
|
VMOVDQA X2, X6
|
|
VMOVDQA X3, X7
|
|
MOVQ Rounds, Tmp0
|
|
|
|
VMOVDQA 6*16(Stack), X9 // Load 16 bit rotate-left constant
|
|
VMOVDQA 7*16(Stack), X10 // Load 8 bit rotate-left constant
|
|
|
|
CHACHA_LOOP_64:
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X8, X9, X10)
|
|
CHACHA_SHUFFLE_AVX(X5, X6, X7)
|
|
CHACHA_QROUND_AVX(X4, X5, X6, X7, X8, X9, X10)
|
|
CHACHA_SHUFFLE_AVX(X7, X6, X5)
|
|
SUBQ $2, Tmp0
|
|
JNZ CHACHA_LOOP_64
|
|
|
|
VPADDD X0, X4, X4
|
|
VPADDD X1, X5, X5
|
|
VPADDD X2, X6, X6
|
|
VPADDD X3, X7, X7
|
|
VPADDQ 4*16(Stack), X3, X3
|
|
|
|
CMPQ Len, $64
|
|
JL BUFFER_KEYSTREAM
|
|
|
|
XOR_AVX(Dst, Src, 0, X4, X5, X6, X7, X8)
|
|
ADDQ $64, Src
|
|
ADDQ $64, Dst
|
|
SUBQ $64, Len
|
|
JMP DONE // jump directly to DONE - there is no keystream to buffer, Len == 0 always true.
|
|
|
|
BUFFER_KEYSTREAM:
|
|
VMOVDQU X4, 0*16(Buffer)
|
|
VMOVDQU X5, 1*16(Buffer)
|
|
VMOVDQU X6, 2*16(Buffer)
|
|
VMOVDQU X7, 3*16(Buffer)
|
|
MOVQ Len, Tmp0
|
|
FINALIZE(Dst, Src, Buffer, Tmp0, Tmp1, Tmp2)
|
|
|
|
DONE:
|
|
MOVQ SavedSP, Stack // Restore stack pointer
|
|
VMOVDQU X3, 3*16(State)
|
|
VZEROUPPER
|
|
MOVQ Len, ret+72(FP)
|
|
RET
|
|
|
|
#undef Dst
|
|
#undef Src
|
|
#undef Len
|
|
#undef Rounds
|
|
#undef Buffer
|
|
#undef State
|
|
#undef Stack
|
|
#undef SavedSP
|
|
#undef Tmp0
|
|
#undef Tmp1
|
|
#undef Tmp2
|