Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * aesce-ccm-core.S - AES-CCM transform for ARMv8 with Crypto Extensions
0004  *
0005  * Copyright (C) 2013 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
0006  */
0007 
0008 #include <linux/linkage.h>
0009 #include <asm/assembler.h>
0010 
0011     .text
0012     .arch   armv8-a+crypto
0013 
0014     /*
0015      * u32 ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes,
0016      *              u32 macp, u8 const rk[], u32 rounds);
0017      */
0018 SYM_FUNC_START(ce_aes_ccm_auth_data)
0019     ld1 {v0.16b}, [x0]          /* load mac */
0020     cbz w3, 1f
0021     sub w3, w3, #16
0022     eor v1.16b, v1.16b, v1.16b
0023 0:  ldrb    w7, [x1], #1            /* get 1 byte of input */
0024     subs    w2, w2, #1
0025     add w3, w3, #1
0026     ins v1.b[0], w7
0027     ext v1.16b, v1.16b, v1.16b, #1  /* rotate in the input bytes */
0028     beq 8f              /* out of input? */
0029     cbnz    w3, 0b
0030     eor v0.16b, v0.16b, v1.16b
0031 1:  ld1 {v3.4s}, [x4]           /* load first round key */
0032     prfm    pldl1strm, [x1]
0033     cmp w5, #12             /* which key size? */
0034     add x6, x4, #16
0035     sub w7, w5, #2          /* modified # of rounds */
0036     bmi 2f
0037     bne 5f
0038     mov v5.16b, v3.16b
0039     b   4f
0040 2:  mov v4.16b, v3.16b
0041     ld1 {v5.4s}, [x6], #16      /* load 2nd round key */
0042 3:  aese    v0.16b, v4.16b
0043     aesmc   v0.16b, v0.16b
0044 4:  ld1 {v3.4s}, [x6], #16      /* load next round key */
0045     aese    v0.16b, v5.16b
0046     aesmc   v0.16b, v0.16b
0047 5:  ld1 {v4.4s}, [x6], #16      /* load next round key */
0048     subs    w7, w7, #3
0049     aese    v0.16b, v3.16b
0050     aesmc   v0.16b, v0.16b
0051     ld1 {v5.4s}, [x6], #16      /* load next round key */
0052     bpl 3b
0053     aese    v0.16b, v4.16b
0054     subs    w2, w2, #16         /* last data? */
0055     eor v0.16b, v0.16b, v5.16b      /* final round */
0056     bmi 6f
0057     ld1 {v1.16b}, [x1], #16     /* load next input block */
0058     eor v0.16b, v0.16b, v1.16b      /* xor with mac */
0059     bne 1b
0060 6:  st1 {v0.16b}, [x0]          /* store mac */
0061     beq 10f
0062     adds    w2, w2, #16
0063     beq 10f
0064     mov w3, w2
0065 7:  ldrb    w7, [x1], #1
0066     umov    w6, v0.b[0]
0067     eor w6, w6, w7
0068     strb    w6, [x0], #1
0069     subs    w2, w2, #1
0070     beq 10f
0071     ext v0.16b, v0.16b, v0.16b, #1  /* rotate out the mac bytes */
0072     b   7b
0073 8:  cbz w3, 91f
0074     mov w7, w3
0075     add w3, w3, #16
0076 9:  ext v1.16b, v1.16b, v1.16b, #1
0077     adds    w7, w7, #1
0078     bne 9b
0079 91: eor v0.16b, v0.16b, v1.16b
0080     st1 {v0.16b}, [x0]
0081 10: mov w0, w3
0082     ret
0083 SYM_FUNC_END(ce_aes_ccm_auth_data)
0084 
0085     /*
0086      * void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u8 const rk[],
0087      *           u32 rounds);
0088      */
0089 SYM_FUNC_START(ce_aes_ccm_final)
0090     ld1 {v3.4s}, [x2], #16      /* load first round key */
0091     ld1 {v0.16b}, [x0]          /* load mac */
0092     cmp w3, #12             /* which key size? */
0093     sub w3, w3, #2          /* modified # of rounds */
0094     ld1 {v1.16b}, [x1]          /* load 1st ctriv */
0095     bmi 0f
0096     bne 3f
0097     mov v5.16b, v3.16b
0098     b   2f
0099 0:  mov v4.16b, v3.16b
0100 1:  ld1 {v5.4s}, [x2], #16      /* load next round key */
0101     aese    v0.16b, v4.16b
0102     aesmc   v0.16b, v0.16b
0103     aese    v1.16b, v4.16b
0104     aesmc   v1.16b, v1.16b
0105 2:  ld1 {v3.4s}, [x2], #16      /* load next round key */
0106     aese    v0.16b, v5.16b
0107     aesmc   v0.16b, v0.16b
0108     aese    v1.16b, v5.16b
0109     aesmc   v1.16b, v1.16b
0110 3:  ld1 {v4.4s}, [x2], #16      /* load next round key */
0111     subs    w3, w3, #3
0112     aese    v0.16b, v3.16b
0113     aesmc   v0.16b, v0.16b
0114     aese    v1.16b, v3.16b
0115     aesmc   v1.16b, v1.16b
0116     bpl 1b
0117     aese    v0.16b, v4.16b
0118     aese    v1.16b, v4.16b
0119     /* final round key cancels out */
0120     eor v0.16b, v0.16b, v1.16b      /* en-/decrypt the mac */
0121     st1 {v0.16b}, [x0]          /* store result */
0122     ret
0123 SYM_FUNC_END(ce_aes_ccm_final)
0124 
0125     .macro  aes_ccm_do_crypt,enc
0126     cbz x2, 5f
0127     ldr x8, [x6, #8]            /* load lower ctr */
0128     ld1 {v0.16b}, [x5]          /* load mac */
0129 CPU_LE( rev x8, x8          )   /* keep swabbed ctr in reg */
0130 0:  /* outer loop */
0131     ld1 {v1.8b}, [x6]           /* load upper ctr */
0132     prfm    pldl1strm, [x1]
0133     add x8, x8, #1
0134     rev x9, x8
0135     cmp w4, #12             /* which key size? */
0136     sub w7, w4, #2          /* get modified # of rounds */
0137     ins v1.d[1], x9         /* no carry in lower ctr */
0138     ld1 {v3.4s}, [x3]           /* load first round key */
0139     add x10, x3, #16
0140     bmi 1f
0141     bne 4f
0142     mov v5.16b, v3.16b
0143     b   3f
0144 1:  mov v4.16b, v3.16b
0145     ld1 {v5.4s}, [x10], #16     /* load 2nd round key */
0146 2:  /* inner loop: 3 rounds, 2x interleaved */
0147     aese    v0.16b, v4.16b
0148     aesmc   v0.16b, v0.16b
0149     aese    v1.16b, v4.16b
0150     aesmc   v1.16b, v1.16b
0151 3:  ld1 {v3.4s}, [x10], #16     /* load next round key */
0152     aese    v0.16b, v5.16b
0153     aesmc   v0.16b, v0.16b
0154     aese    v1.16b, v5.16b
0155     aesmc   v1.16b, v1.16b
0156 4:  ld1 {v4.4s}, [x10], #16     /* load next round key */
0157     subs    w7, w7, #3
0158     aese    v0.16b, v3.16b
0159     aesmc   v0.16b, v0.16b
0160     aese    v1.16b, v3.16b
0161     aesmc   v1.16b, v1.16b
0162     ld1 {v5.4s}, [x10], #16     /* load next round key */
0163     bpl 2b
0164     aese    v0.16b, v4.16b
0165     aese    v1.16b, v4.16b
0166     subs    w2, w2, #16
0167     bmi 6f              /* partial block? */
0168     ld1 {v2.16b}, [x1], #16     /* load next input block */
0169     .if \enc == 1
0170     eor v2.16b, v2.16b, v5.16b      /* final round enc+mac */
0171     eor v1.16b, v1.16b, v2.16b      /* xor with crypted ctr */
0172     .else
0173     eor v2.16b, v2.16b, v1.16b      /* xor with crypted ctr */
0174     eor v1.16b, v2.16b, v5.16b      /* final round enc */
0175     .endif
0176     eor v0.16b, v0.16b, v2.16b      /* xor mac with pt ^ rk[last] */
0177     st1 {v1.16b}, [x0], #16     /* write output block */
0178     bne 0b
0179 CPU_LE( rev x8, x8          )
0180     st1 {v0.16b}, [x5]          /* store mac */
0181     str x8, [x6, #8]            /* store lsb end of ctr (BE) */
0182 5:  ret
0183 
0184 6:  eor v0.16b, v0.16b, v5.16b      /* final round mac */
0185     eor v1.16b, v1.16b, v5.16b      /* final round enc */
0186     st1 {v0.16b}, [x5]          /* store mac */
0187     add w2, w2, #16         /* process partial tail block */
0188 7:  ldrb    w9, [x1], #1            /* get 1 byte of input */
0189     umov    w6, v1.b[0]         /* get top crypted ctr byte */
0190     umov    w7, v0.b[0]         /* get top mac byte */
0191     .if \enc == 1
0192     eor w7, w7, w9
0193     eor w9, w9, w6
0194     .else
0195     eor w9, w9, w6
0196     eor w7, w7, w9
0197     .endif
0198     strb    w9, [x0], #1            /* store out byte */
0199     strb    w7, [x5], #1            /* store mac byte */
0200     subs    w2, w2, #1
0201     beq 5b
0202     ext v0.16b, v0.16b, v0.16b, #1  /* shift out mac byte */
0203     ext v1.16b, v1.16b, v1.16b, #1  /* shift out ctr byte */
0204     b   7b
0205     .endm
0206 
0207     /*
0208      * void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,
0209      *             u8 const rk[], u32 rounds, u8 mac[],
0210      *             u8 ctr[]);
0211      * void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
0212      *             u8 const rk[], u32 rounds, u8 mac[],
0213      *             u8 ctr[]);
0214      */
0215 SYM_FUNC_START(ce_aes_ccm_encrypt)
0216     aes_ccm_do_crypt    1
0217 SYM_FUNC_END(ce_aes_ccm_encrypt)
0218 
0219 SYM_FUNC_START(ce_aes_ccm_decrypt)
0220     aes_ccm_do_crypt    0
0221 SYM_FUNC_END(ce_aes_ccm_decrypt)