Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-2.6-block.git] / arch / x86 / crypto / aesni-intel_asm.S
index 3d09e3aca18dad33ba0c27c3673e49dcbfac0ce8..12e8484a8ee79b42d3604abc71a6e53a0f5b4cee 100644 (file)
@@ -90,30 +90,6 @@ SHIFT_MASK: .octa 0x0f0e0d0c0b0a09080706050403020100
 ALL_F:      .octa 0xffffffffffffffffffffffffffffffff
             .octa 0x00000000000000000000000000000000
 
-.section .rodata
-.align 16
-.type aad_shift_arr, @object
-.size aad_shift_arr, 272
-aad_shift_arr:
-        .octa     0xffffffffffffffffffffffffffffffff
-        .octa     0xffffffffffffffffffffffffffffff0C
-        .octa     0xffffffffffffffffffffffffffff0D0C
-        .octa     0xffffffffffffffffffffffffff0E0D0C
-        .octa     0xffffffffffffffffffffffff0F0E0D0C
-        .octa     0xffffffffffffffffffffff0C0B0A0908
-        .octa     0xffffffffffffffffffff0D0C0B0A0908
-        .octa     0xffffffffffffffffff0E0D0C0B0A0908
-        .octa     0xffffffffffffffff0F0E0D0C0B0A0908
-        .octa     0xffffffffffffff0C0B0A090807060504
-        .octa     0xffffffffffff0D0C0B0A090807060504
-        .octa     0xffffffffff0E0D0C0B0A090807060504
-        .octa     0xffffffff0F0E0D0C0B0A090807060504
-        .octa     0xffffff0C0B0A09080706050403020100
-        .octa     0xffff0D0C0B0A09080706050403020100
-        .octa     0xff0E0D0C0B0A09080706050403020100
-        .octa     0x0F0E0D0C0B0A09080706050403020100
-
-
 .text
 
 
@@ -257,6 +233,37 @@ aad_shift_arr:
        pxor      \TMP1, \GH            # result is in TMP1
 .endm
 
+# Reads DLEN bytes starting at DPTR and stores in XMMDst
+# where 0 < DLEN < 16
+# Clobbers %rax, DLEN and XMM1
+.macro READ_PARTIAL_BLOCK DPTR DLEN XMM1 XMMDst
+        cmp $8, \DLEN
+        jl _read_lt8_\@
+        mov (\DPTR), %rax
+        MOVQ_R64_XMM %rax, \XMMDst
+        sub $8, \DLEN
+        jz _done_read_partial_block_\@
+       xor %eax, %eax
+_read_next_byte_\@:
+        shl $8, %rax
+        mov 7(\DPTR, \DLEN, 1), %al
+        dec \DLEN
+        jnz _read_next_byte_\@
+        MOVQ_R64_XMM %rax, \XMM1
+       pslldq $8, \XMM1
+        por \XMM1, \XMMDst
+       jmp _done_read_partial_block_\@
+_read_lt8_\@:
+       xor %eax, %eax
+_read_next_byte_lt8_\@:
+        shl $8, %rax
+        mov -1(\DPTR, \DLEN, 1), %al
+        dec \DLEN
+        jnz _read_next_byte_lt8_\@
+        MOVQ_R64_XMM %rax, \XMMDst
+_done_read_partial_block_\@:
+.endm
+
 /*
 * if a = number of total plaintext bytes
 * b = floor(a/16)
@@ -273,62 +280,30 @@ aad_shift_arr:
 XMM2 XMM3 XMM4 XMMDst TMP6 TMP7 i i_seq operation
         MOVADQ     SHUF_MASK(%rip), %xmm14
        mov        arg7, %r10           # %r10 = AAD
-       mov        arg8, %r12           # %r12 = aadLen
-       mov        %r12, %r11
+       mov        arg8, %r11           # %r11 = aadLen
        pxor       %xmm\i, %xmm\i
        pxor       \XMM2, \XMM2
 
        cmp        $16, %r11
-       jl         _get_AAD_rest8\num_initial_blocks\operation
+       jl         _get_AAD_rest\num_initial_blocks\operation
 _get_AAD_blocks\num_initial_blocks\operation:
        movdqu     (%r10), %xmm\i
        PSHUFB_XMM %xmm14, %xmm\i # byte-reflect the AAD data
        pxor       %xmm\i, \XMM2
        GHASH_MUL  \XMM2, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
        add        $16, %r10
-       sub        $16, %r12
        sub        $16, %r11
        cmp        $16, %r11
        jge        _get_AAD_blocks\num_initial_blocks\operation
 
        movdqu     \XMM2, %xmm\i
+
+       /* read the last <16B of AAD */
+_get_AAD_rest\num_initial_blocks\operation:
        cmp        $0, %r11
        je         _get_AAD_done\num_initial_blocks\operation
 
-       pxor       %xmm\i,%xmm\i
-
-       /* read the last <16B of AAD. since we have at least 4B of
-       data right after the AAD (the ICV, and maybe some CT), we can
-       read 4B/8B blocks safely, and then get rid of the extra stuff */
-_get_AAD_rest8\num_initial_blocks\operation:
-       cmp        $4, %r11
-       jle        _get_AAD_rest4\num_initial_blocks\operation
-       movq       (%r10), \TMP1
-       add        $8, %r10
-       sub        $8, %r11
-       pslldq     $8, \TMP1
-       psrldq     $8, %xmm\i
-       pxor       \TMP1, %xmm\i
-       jmp        _get_AAD_rest8\num_initial_blocks\operation
-_get_AAD_rest4\num_initial_blocks\operation:
-       cmp        $0, %r11
-       jle        _get_AAD_rest0\num_initial_blocks\operation
-       mov        (%r10), %eax
-       movq       %rax, \TMP1
-       add        $4, %r10
-       sub        $4, %r10
-       pslldq     $12, \TMP1
-       psrldq     $4, %xmm\i
-       pxor       \TMP1, %xmm\i
-_get_AAD_rest0\num_initial_blocks\operation:
-       /* finalize: shift out the extra bytes we read, and align
-       left. since pslldq can only shift by an immediate, we use
-       vpshufb and an array of shuffle masks */
-       movq       %r12, %r11
-       salq       $4, %r11
-       movdqu     aad_shift_arr(%r11), \TMP1
-       PSHUFB_XMM \TMP1, %xmm\i
-_get_AAD_rest_final\num_initial_blocks\operation:
+       READ_PARTIAL_BLOCK %r10, %r11, \TMP1, %xmm\i
        PSHUFB_XMM   %xmm14, %xmm\i # byte-reflect the AAD data
        pxor       \XMM2, %xmm\i
        GHASH_MUL  %xmm\i, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
@@ -532,62 +507,30 @@ _initial_blocks_done\num_initial_blocks\operation:
 XMM2 XMM3 XMM4 XMMDst TMP6 TMP7 i i_seq operation
         MOVADQ     SHUF_MASK(%rip), %xmm14
        mov        arg7, %r10           # %r10 = AAD
-       mov        arg8, %r12           # %r12 = aadLen
-       mov        %r12, %r11
+       mov        arg8, %r11           # %r11 = aadLen
        pxor       %xmm\i, %xmm\i
        pxor       \XMM2, \XMM2
 
        cmp        $16, %r11
-       jl         _get_AAD_rest8\num_initial_blocks\operation
+       jl         _get_AAD_rest\num_initial_blocks\operation
 _get_AAD_blocks\num_initial_blocks\operation:
        movdqu     (%r10), %xmm\i
        PSHUFB_XMM   %xmm14, %xmm\i # byte-reflect the AAD data
        pxor       %xmm\i, \XMM2
        GHASH_MUL  \XMM2, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
        add        $16, %r10
-       sub        $16, %r12
        sub        $16, %r11
        cmp        $16, %r11
        jge        _get_AAD_blocks\num_initial_blocks\operation
 
        movdqu     \XMM2, %xmm\i
+
+       /* read the last <16B of AAD */
+_get_AAD_rest\num_initial_blocks\operation:
        cmp        $0, %r11
        je         _get_AAD_done\num_initial_blocks\operation
 
-       pxor       %xmm\i,%xmm\i
-
-       /* read the last <16B of AAD. since we have at least 4B of
-       data right after the AAD (the ICV, and maybe some PT), we can
-       read 4B/8B blocks safely, and then get rid of the extra stuff */
-_get_AAD_rest8\num_initial_blocks\operation:
-       cmp        $4, %r11
-       jle        _get_AAD_rest4\num_initial_blocks\operation
-       movq       (%r10), \TMP1
-       add        $8, %r10
-       sub        $8, %r11
-       pslldq     $8, \TMP1
-       psrldq     $8, %xmm\i
-       pxor       \TMP1, %xmm\i
-       jmp        _get_AAD_rest8\num_initial_blocks\operation
-_get_AAD_rest4\num_initial_blocks\operation:
-       cmp        $0, %r11
-       jle        _get_AAD_rest0\num_initial_blocks\operation
-       mov        (%r10), %eax
-       movq       %rax, \TMP1
-       add        $4, %r10
-       sub        $4, %r10
-       pslldq     $12, \TMP1
-       psrldq     $4, %xmm\i
-       pxor       \TMP1, %xmm\i
-_get_AAD_rest0\num_initial_blocks\operation:
-       /* finalize: shift out the extra bytes we read, and align
-       left. since pslldq can only shift by an immediate, we use
-       vpshufb and an array of shuffle masks */
-       movq       %r12, %r11
-       salq       $4, %r11
-       movdqu     aad_shift_arr(%r11), \TMP1
-       PSHUFB_XMM \TMP1, %xmm\i
-_get_AAD_rest_final\num_initial_blocks\operation:
+       READ_PARTIAL_BLOCK %r10, %r11, \TMP1, %xmm\i
        PSHUFB_XMM   %xmm14, %xmm\i # byte-reflect the AAD data
        pxor       \XMM2, %xmm\i
        GHASH_MUL  %xmm\i, \TMP3, \TMP1, \TMP2, \TMP4, \TMP5, \XMM1
@@ -1386,14 +1329,6 @@ _esb_loop_\@:
 *
 *                        AAD Format with 64-bit Extended Sequence Number
 *
-* aadLen:
-*       from the definition of the spec, aadLen can only be 8 or 12 bytes.
-*       The code supports 16 too but for other sizes, the code will fail.
-*
-* TLen:
-*       from the definition of the spec, TLen can only be 8, 12 or 16 bytes.
-*       For other sizes, the code will fail.
-*
 * poly = x^128 + x^127 + x^126 + x^121 + 1
 *
 *****************************************************************************/
@@ -1487,19 +1422,16 @@ _zero_cipher_left_decrypt:
        PSHUFB_XMM %xmm10, %xmm0
 
        ENCRYPT_SINGLE_BLOCK  %xmm0, %xmm1    # E(K, Yn)
-       sub $16, %r11
-       add %r13, %r11
-       movdqu (%arg3,%r11,1), %xmm1   # receive the last <16 byte block
-       lea SHIFT_MASK+16(%rip), %r12
-       sub %r13, %r12
-# adjust the shuffle mask pointer to be able to shift 16-%r13 bytes
-# (%r13 is the number of bytes in plaintext mod 16)
-       movdqu (%r12), %xmm2           # get the appropriate shuffle mask
-       PSHUFB_XMM %xmm2, %xmm1            # right shift 16-%r13 butes
 
+       lea (%arg3,%r11,1), %r10
+       mov %r13, %r12
+       READ_PARTIAL_BLOCK %r10 %r12 %xmm2 %xmm1
+
+       lea ALL_F+16(%rip), %r12
+       sub %r13, %r12
        movdqa  %xmm1, %xmm2
        pxor %xmm1, %xmm0            # Ciphertext XOR E(K, Yn)
-       movdqu ALL_F-SHIFT_MASK(%r12), %xmm1
+       movdqu (%r12), %xmm1
        # get the appropriate mask to mask out top 16-%r13 bytes of %xmm0
        pand %xmm1, %xmm0            # mask out top 16-%r13 bytes of %xmm0
        pand    %xmm1, %xmm2
@@ -1508,9 +1440,6 @@ _zero_cipher_left_decrypt:
 
        pxor %xmm2, %xmm8
        GHASH_MUL %xmm8, %xmm13, %xmm9, %xmm10, %xmm11, %xmm5, %xmm6
-                 # GHASH computation for the last <16 byte block
-       sub %r13, %r11
-       add $16, %r11
 
         # output %r13 bytes
        MOVQ_R64_XMM    %xmm0, %rax
@@ -1664,14 +1593,6 @@ ENDPROC(aesni_gcm_dec)
 *
 *                         AAD Format with 64-bit Extended Sequence Number
 *
-* aadLen:
-*       from the definition of the spec, aadLen can only be 8 or 12 bytes.
-*       The code supports 16 too but for other sizes, the code will fail.
-*
-* TLen:
-*       from the definition of the spec, TLen can only be 8, 12 or 16 bytes.
-*       For other sizes, the code will fail.
-*
 * poly = x^128 + x^127 + x^126 + x^121 + 1
 ***************************************************************************/
 ENTRY(aesni_gcm_enc)
@@ -1764,19 +1685,16 @@ _zero_cipher_left_encrypt:
         movdqa SHUF_MASK(%rip), %xmm10
        PSHUFB_XMM %xmm10, %xmm0
 
-
        ENCRYPT_SINGLE_BLOCK    %xmm0, %xmm1        # Encrypt(K, Yn)
-       sub $16, %r11
-       add %r13, %r11
-       movdqu (%arg3,%r11,1), %xmm1     # receive the last <16 byte blocks
-       lea SHIFT_MASK+16(%rip), %r12
+
+       lea (%arg3,%r11,1), %r10
+       mov %r13, %r12
+       READ_PARTIAL_BLOCK %r10 %r12 %xmm2 %xmm1
+
+       lea ALL_F+16(%rip), %r12
        sub %r13, %r12
-       # adjust the shuffle mask pointer to be able to shift 16-r13 bytes
-       # (%r13 is the number of bytes in plaintext mod 16)
-       movdqu  (%r12), %xmm2           # get the appropriate shuffle mask
-       PSHUFB_XMM      %xmm2, %xmm1            # shift right 16-r13 byte
        pxor    %xmm1, %xmm0            # Plaintext XOR Encrypt(K, Yn)
-       movdqu  ALL_F-SHIFT_MASK(%r12), %xmm1
+       movdqu  (%r12), %xmm1
        # get the appropriate mask to mask out top 16-r13 bytes of xmm0
        pand    %xmm1, %xmm0            # mask out top 16-r13 bytes of xmm0
         movdqa SHUF_MASK(%rip), %xmm10
@@ -1785,9 +1703,6 @@ _zero_cipher_left_encrypt:
        pxor    %xmm0, %xmm8
        GHASH_MUL %xmm8, %xmm13, %xmm9, %xmm10, %xmm11, %xmm5, %xmm6
        # GHASH computation for the last <16 byte block
-       sub     %r13, %r11
-       add     $16, %r11
-
        movdqa SHUF_MASK(%rip), %xmm10
        PSHUFB_XMM %xmm10, %xmm0