@@ -51,6 +51,8 @@ type gcmAsm struct {
51
51
tagSize int
52
52
}
53
53
54
+ func counterCryptASM (nr int , out , in []byte , counter * [gcmBlockSize ]byte , key * uint32 )
55
+
54
56
// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only
55
57
// called by crypto/cipher.NewGCM via the gcmAble interface.
56
58
func (c * aesCipherAsm ) NewGCM (nonceSize , tagSize int ) (cipher.AEAD , error ) {
@@ -114,34 +116,10 @@ func (g *gcmAsm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) {
114
116
// into out. counter is the initial count value and will be updated with the next
115
117
// count value. The length of out must be greater than or equal to the length
116
118
// of in.
119
+ // counterCryptASM implements counterCrypt which then allows the loop to
120
+ // be unrolled and optimized.
117
121
func (g * gcmAsm ) counterCrypt (out , in []byte , counter * [gcmBlockSize ]byte ) {
118
- var mask [gcmBlockSize ]byte
119
-
120
- for len (in ) >= gcmBlockSize {
121
- // Hint to avoid bounds check
122
- _ , _ = in [15 ], out [15 ]
123
- g .cipher .Encrypt (mask [:], counter [:])
124
- gcmInc32 (counter )
125
-
126
- // XOR 16 bytes each loop iteration in 8 byte chunks
127
- in0 := binary .LittleEndian .Uint64 (in [0 :])
128
- in1 := binary .LittleEndian .Uint64 (in [8 :])
129
- m0 := binary .LittleEndian .Uint64 (mask [:8 ])
130
- m1 := binary .LittleEndian .Uint64 (mask [8 :])
131
- binary .LittleEndian .PutUint64 (out [:8 ], in0 ^ m0 )
132
- binary .LittleEndian .PutUint64 (out [8 :], in1 ^ m1 )
133
- out = out [16 :]
134
- in = in [16 :]
135
- }
136
-
137
- if len (in ) > 0 {
138
- g .cipher .Encrypt (mask [:], counter [:])
139
- gcmInc32 (counter )
140
- // XOR leftover bytes
141
- for i , inb := range in {
142
- out [i ] = inb ^ mask [i ]
143
- }
144
- }
122
+ counterCryptASM (len (g .cipher .enc )/ 4 - 1 , out , in , counter , & g .cipher .enc [0 ])
145
123
}
146
124
147
125
// increments the rightmost 32-bits of the count value by 1.
0 commit comments