vgetrandom-chacha.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include <linux/stringify.h>
  3. #include <linux/linkage.h>
  4. #include <asm/alternative.h>
  5. #include <asm/dwarf.h>
  6. #include <asm/fpu-insn.h>
  7. #define STATE0 %v0
  8. #define STATE1 %v1
  9. #define STATE2 %v2
  10. #define STATE3 %v3
  11. #define COPY0 %v4
  12. #define COPY1 %v5
  13. #define COPY2 %v6
  14. #define COPY3 %v7
  15. #define BEPERM %v19
  16. #define TMP0 %v20
  17. #define TMP1 %v21
  18. #define TMP2 %v22
  19. #define TMP3 %v23
  20. .section .rodata
  21. .balign 32
  22. SYM_DATA_START_LOCAL(chacha20_constants)
  23. .long 0x61707865,0x3320646e,0x79622d32,0x6b206574 # endian-neutral
  24. .long 0x03020100,0x07060504,0x0b0a0908,0x0f0e0d0c # byte swap
  25. SYM_DATA_END(chacha20_constants)
  26. .text
  27. /*
  28. * s390 ChaCha20 implementation meant for vDSO. Produces a given positive
  29. * number of blocks of output with nonce 0, taking an input key and 8-bytes
  30. * counter. Does not spill to the stack.
  31. *
  32. * void __arch_chacha20_blocks_nostack(uint8_t *dst_bytes,
  33. * const uint8_t *key,
  34. * uint32_t *counter,
  35. * size_t nblocks)
  36. */
  37. SYM_FUNC_START(__arch_chacha20_blocks_nostack)
  38. CFI_STARTPROC
  39. larl %r1,chacha20_constants
  40. /* COPY0 = "expand 32-byte k" */
  41. VL COPY0,0,,%r1
  42. /* BEPERM = byte selectors for VPERM */
  43. ALTERNATIVE __stringify(VL BEPERM,16,,%r1), "brcl 0,0", ALT_FACILITY(148)
  44. /* COPY1,COPY2 = key */
  45. VLM COPY1,COPY2,0,%r3
  46. /* COPY3 = counter || zero nonce */
  47. lg %r3,0(%r4)
  48. VZERO COPY3
  49. VLVGG COPY3,%r3,0
  50. lghi %r1,0
  51. .Lblock:
  52. VLR STATE0,COPY0
  53. VLR STATE1,COPY1
  54. VLR STATE2,COPY2
  55. VLR STATE3,COPY3
  56. lghi %r0,10
  57. .Ldoubleround:
  58. /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 16) */
  59. VAF STATE0,STATE0,STATE1
  60. VX STATE3,STATE3,STATE0
  61. VERLLF STATE3,STATE3,16
  62. /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 12) */
  63. VAF STATE2,STATE2,STATE3
  64. VX STATE1,STATE1,STATE2
  65. VERLLF STATE1,STATE1,12
  66. /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 8) */
  67. VAF STATE0,STATE0,STATE1
  68. VX STATE3,STATE3,STATE0
  69. VERLLF STATE3,STATE3,8
  70. /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 7) */
  71. VAF STATE2,STATE2,STATE3
  72. VX STATE1,STATE1,STATE2
  73. VERLLF STATE1,STATE1,7
  74. /* STATE1[0,1,2,3] = STATE1[1,2,3,0] */
  75. VSLDB STATE1,STATE1,STATE1,4
  76. /* STATE2[0,1,2,3] = STATE2[2,3,0,1] */
  77. VSLDB STATE2,STATE2,STATE2,8
  78. /* STATE3[0,1,2,3] = STATE3[3,0,1,2] */
  79. VSLDB STATE3,STATE3,STATE3,12
  80. /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 16) */
  81. VAF STATE0,STATE0,STATE1
  82. VX STATE3,STATE3,STATE0
  83. VERLLF STATE3,STATE3,16
  84. /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 12) */
  85. VAF STATE2,STATE2,STATE3
  86. VX STATE1,STATE1,STATE2
  87. VERLLF STATE1,STATE1,12
  88. /* STATE0 += STATE1, STATE3 = rotl32(STATE3 ^ STATE0, 8) */
  89. VAF STATE0,STATE0,STATE1
  90. VX STATE3,STATE3,STATE0
  91. VERLLF STATE3,STATE3,8
  92. /* STATE2 += STATE3, STATE1 = rotl32(STATE1 ^ STATE2, 7) */
  93. VAF STATE2,STATE2,STATE3
  94. VX STATE1,STATE1,STATE2
  95. VERLLF STATE1,STATE1,7
  96. /* STATE1[0,1,2,3] = STATE1[3,0,1,2] */
  97. VSLDB STATE1,STATE1,STATE1,12
  98. /* STATE2[0,1,2,3] = STATE2[2,3,0,1] */
  99. VSLDB STATE2,STATE2,STATE2,8
  100. /* STATE3[0,1,2,3] = STATE3[1,2,3,0] */
  101. VSLDB STATE3,STATE3,STATE3,4
  102. brctg %r0,.Ldoubleround
  103. /* OUTPUT0 = STATE0 + COPY0 */
  104. VAF STATE0,STATE0,COPY0
  105. /* OUTPUT1 = STATE1 + COPY1 */
  106. VAF STATE1,STATE1,COPY1
  107. /* OUTPUT2 = STATE2 + COPY2 */
  108. VAF STATE2,STATE2,COPY2
  109. /* OUTPUT3 = STATE3 + COPY3 */
  110. VAF STATE3,STATE3,COPY3
  111. ALTERNATIVE \
  112. __stringify( \
  113. /* Convert STATE to little endian and store to OUTPUT */\
  114. VPERM TMP0,STATE0,STATE0,BEPERM; \
  115. VPERM TMP1,STATE1,STATE1,BEPERM; \
  116. VPERM TMP2,STATE2,STATE2,BEPERM; \
  117. VPERM TMP3,STATE3,STATE3,BEPERM; \
  118. VSTM TMP0,TMP3,0,%r2), \
  119. __stringify( \
  120. /* 32 bit wise little endian store to OUTPUT */ \
  121. VSTBRF STATE0,0,,%r2; \
  122. VSTBRF STATE1,16,,%r2; \
  123. VSTBRF STATE2,32,,%r2; \
  124. VSTBRF STATE3,48,,%r2; \
  125. brcl 0,0), \
  126. ALT_FACILITY(148)
  127. /* ++COPY3.COUNTER */
  128. /* alsih %r3,1 */
  129. .insn rilu,0xcc0a00000000,%r3,1
  130. alcr %r3,%r1
  131. VLVGG COPY3,%r3,0
  132. /* OUTPUT += 64, --NBLOCKS */
  133. aghi %r2,64
  134. brctg %r5,.Lblock
  135. /* COUNTER = COPY3.COUNTER */
  136. stg %r3,0(%r4)
  137. /* Zero out potentially sensitive regs */
  138. VZERO STATE0
  139. VZERO STATE1
  140. VZERO STATE2
  141. VZERO STATE3
  142. VZERO COPY1
  143. VZERO COPY2
  144. /* Early exit if TMP0-TMP3 have not been used */
  145. ALTERNATIVE "nopr", "br %r14", ALT_FACILITY(148)
  146. VZERO TMP0
  147. VZERO TMP1
  148. VZERO TMP2
  149. VZERO TMP3
  150. br %r14
  151. CFI_ENDPROC
  152. SYM_FUNC_END(__arch_chacha20_blocks_nostack)