aesarm.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * This file is adapted from https://github.com/CriticalBlue/mbedtls
  3. */
  4. /*
  5. * ARMv8-A Cryptography Extension AES support functions
  6. *
  7. * Copyright (C) 2016, CriticalBlue Limited, All Rights Reserved
  8. * SPDX-License-Identifier: Apache-2.0
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  11. * not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  18. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. *
  22. * This file is part of mbed TLS (https://tls.mbed.org)
  23. */
  24. #include "aesarm.h"
  25. #if defined(HAVE_ARM64)
  26. #include <sys/auxv.h>
  27. #include <asm/hwcap.h>
  28. #include <arm_neon.h>
  29. /*
  30. * ARMv8a Crypto Extension support detection routine
  31. */
  32. int aesarm_supported( void )
  33. {
  34. static int done = 0;
  35. static unsigned int c = 0;
  36. if ( ! done )
  37. {
  38. c = getauxval(AT_HWCAP);
  39. done = 1;
  40. }
  41. return ( c & HWCAP_AES ) != 0;
  42. }
  43. /*
  44. * ARMv8a AES-ECB block en(de)cryption
  45. */
  46. void aesarm_crypt_ecb( int nr,
  47. unsigned char *rk,
  48. int mode,
  49. const unsigned char input[16],
  50. unsigned char output[16] )
  51. {
  52. int i;
  53. uint8x16_t state_vec, roundkey_vec;
  54. uint8_t *RK = (uint8_t *) rk;
  55. // Load input and round key into into their vectors
  56. state_vec = vld1q_u8( input );
  57. if ( mode == AES_ENCRYPT )
  58. {
  59. // Initial AddRoundKey is in the loop due to AES instruction always doing AddRoundKey first
  60. for( i = 0; i < nr - 1; i++ )
  61. {
  62. // Load Round Key
  63. roundkey_vec = vld1q_u8( RK );
  64. // Forward (AESE) round (AddRoundKey, SubBytes and ShiftRows)
  65. state_vec = vaeseq_u8( state_vec, roundkey_vec );
  66. // Mix Columns (AESMC)
  67. state_vec = vaesmcq_u8( state_vec );
  68. // Move pointer ready to load next round key
  69. RK += 16;
  70. }
  71. // Final Forward (AESE) round (AddRoundKey, SubBytes and ShiftRows). No Mix columns
  72. roundkey_vec = vld1q_u8( RK ); /* RK already moved in loop */
  73. state_vec = vaeseq_u8( state_vec, roundkey_vec );
  74. }
  75. else
  76. {
  77. // Initial AddRoundKey is in the loop due to AES instruction always doing AddRoundKey first
  78. for( i = 0; i < nr - 1; i++ )
  79. {
  80. // Load Round Key
  81. roundkey_vec = vld1q_u8( RK );
  82. // Reverse (AESD) round (AddRoundKey, SubBytes and ShiftRows)
  83. state_vec = vaesdq_u8( state_vec, roundkey_vec );
  84. // Inverse Mix Columns (AESIMC)
  85. state_vec = vaesimcq_u8( state_vec );
  86. // Move pointer ready to load next round key
  87. RK += 16;
  88. }
  89. // Final Reverse (AESD) round (AddRoundKey, SubBytes and ShiftRows). No Mix columns
  90. roundkey_vec = vld1q_u8( RK ); /* RK already moved in loop */
  91. state_vec = vaesdq_u8( state_vec, roundkey_vec );
  92. }
  93. // Manually apply final Add RoundKey step (EOR)
  94. RK += 16;
  95. roundkey_vec = vld1q_u8( RK );
  96. state_vec = veorq_u8( state_vec, roundkey_vec );
  97. // Write results back to output array
  98. vst1q_u8( output, state_vec );
  99. }
  100. #endif /* HAVE_ARM64 */