Coverage report: /home/ellis/comp/ext/ironclad/src/macs/gmac.lisp
Kind | Covered | All | % |
expression | 0 | 506 | 0.0 |
branch | 0 | 46 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;;; gmac.lisp -- GMAC message authentication code
2
;; See nistspecialpublication800-38d.pdf about GCM and GMAC.
6
((accumulator :accessor gmac-accumulator
7
:initform (make-array 16 :element-type '(unsigned-byte 8))
8
:type (simple-array (unsigned-byte 8) (16)))
9
(key :accessor gmac-key
11
(simple-array (unsigned-byte 8) (16))
12
(simple-array (unsigned-byte 64) (128 2 2))))
13
(total-length :accessor gmac-total-length
15
:type (unsigned-byte 64))
16
(cipher :accessor gmac-cipher
19
:type (simple-array (unsigned-byte 8) (16)))
21
:initform (make-array 16 :element-type '(unsigned-byte 8))
22
:type (simple-array (unsigned-byte 8) (16)))
23
(buffer :accessor gmac-buffer
24
:initform (make-array 16 :element-type '(unsigned-byte 8))
25
:type (simple-array (unsigned-byte 8) (16)))
26
(buffer-length :accessor gmac-buffer-length
28
:type (integer 0 16))))
30
(defun make-gmac (key cipher-name initialization-vector)
31
(unless (member (length key) (key-lengths cipher-name))
32
(error 'invalid-mac-parameter
34
:message "The key length is not compatible with the cipher"))
35
(unless (= (block-length cipher-name) 16)
36
(error 'invalid-mac-parameter
38
:message "GMAC only supports 128-bit block ciphers"))
41
:cipher-name cipher-name
42
:initialization-vector initialization-vector))
44
(declaim (inline gmac-swap-16))
45
(defun gmac-swap-16 (data)
46
(declare (type (simple-array (unsigned-byte 8) (16)) data)
47
(optimize (speed 3) (space 0) (safety 0) (debug 0)))
48
(let ((x (ub64ref/be data 8)))
49
(declare (type (unsigned-byte 64) x))
50
(setf (ub64ref/le data 8) (ub64ref/be data 0)
51
(ub64ref/le data 0) x))
55
(multiple-value-bind (q r) (floor (length x) 16)
57
(let ((z (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0))
59
(if #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
60
#-(and x86-64 ironclad-assembly) nil
61
(let ((y (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0)))
63
(replace y x :start2 i)
64
(ironclad::gmac-swap-16 y)
65
(ironclad::xor-block 16 z 0 y 0 z 0)
66
(ironclad::gmac-mul z h)
68
(ironclad::gmac-swap-16 z))
70
(ironclad::xor-block 16 z 0 x i z 0)
71
(ironclad::gmac-mul z h)
77
(make-array (- (* 16 (ceiling n 16)) n)
78
:element-type '(unsigned-byte 8)
83
(concatenate '(simple-array (unsigned-byte 8) (*))
88
(integer-to-octets (* 8 an) :n-bits 64)
89
(integer-to-octets (* 8 cn) :n-bits 64)))))
90
(let* ((n (length iv))
94
(concatenate '(simple-array (unsigned-byte 8) (16)) iv #(0 0 0 1)))
95
((< 0 n*8 #.(expt 2 64))
96
(ghash h (ac nil iv)))
98
(error 'invalid-mac-parameter
100
:message "iv size not in range 0<|iv|<2^64 bits"))))))
102
(defmethod shared-initialize :after ((mac gmac) slot-names &rest initargs &key key cipher-name initialization-vector &allow-other-keys)
103
(declare (ignore slot-names initargs)
104
(type (simple-array (unsigned-byte 8) (*)) key))
105
(when (and cipher-name (/= (block-length cipher-name) 16))
106
(error 'invalid-mac-parameter
108
:message "GMAC only supports 128-bit block ciphers"))
109
(if #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
110
#-(and x86-64 ironclad-assembly) nil
111
(let ((cipher (if (or cipher-name (null (gmac-cipher mac)))
112
(make-cipher cipher-name :key key :mode :ecb)
113
(reinitialize-instance (gmac-cipher mac) :key key :mode :ecb)))
114
(hkey (make-array 16 :element-type '(unsigned-byte 8)))
116
(declare (type (simple-array (unsigned-byte 8) (16)) hkey))
117
(setf (gmac-key mac) hkey
118
(gmac-total-length mac) 0
119
(gmac-buffer-length mac) 0
120
(gmac-cipher mac) cipher)
121
(fill (gmac-accumulator mac) 0)
123
(encrypt-in-place cipher hkey)
125
(let ((j0 (j0 hkey initialization-vector)))
126
(setf (gmac-j0 mac) j0)
128
(encrypt-in-place cipher iv)
130
(let ((table (make-array '(128 2 2) :element-type '(unsigned-byte 64)
132
(cipher (if cipher-name
133
(make-cipher cipher-name :key key :mode :ecb)
136
(hkey (make-array 16 :element-type '(unsigned-byte 8)
137
:initial-element 0)))
138
(declare (type (simple-array (unsigned-byte 64) (128 2 2)) table)
139
(type (simple-array (unsigned-byte 8) (16)) hkey)
140
(dynamic-extent hkey))
141
(setf (gmac-key mac) table
142
(gmac-total-length mac) 0
143
(gmac-buffer-length mac) 0
144
(gmac-cipher mac) cipher)
145
(fill (gmac-accumulator mac) 0)
146
(encrypt-in-place cipher hkey)
148
(setf (aref table 0 1 0) (ub64ref/be hkey 0)
149
(aref table 0 1 1) (ub64ref/be hkey 8))
151
(let ((c (if (logbitp 0 (aref table i 1 1)) #xe100000000000000 0)))
152
(declare (type (unsigned-byte 64) c))
153
(setf (aref table (1+ i) 1 1) (logior (mod64ash (aref table i 1 1) -1)
154
(mod64ash (aref table i 1 0) 63))
155
(aref table (1+ i) 1 0) (logxor (mod64ash (aref table i 1 0) -1) c))))
156
(let ((j0 (j0 table initialization-vector)))
157
(setf (gmac-j0 mac) j0)
159
(encrypt-in-place cipher iv)
162
(defun gmac-mul (accumulator key)
163
(declare (type (simple-array (unsigned-byte 8) (16)) accumulator)
164
(optimize (speed 3) (space 0) (safety 0) (debug 0)))
165
(if #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
166
#-(and x86-64 ironclad-assembly) nil
167
#+(and x86-64 ironclad-assembly) (gmac-mul-fast accumulator key)
168
#-(and x86-64 ironclad-assembly) nil
173
(declare (type (simple-array (unsigned-byte 64) (128 2 2)) key)
174
(type (unsigned-byte 8) x)
175
(type (unsigned-byte 64) z0 z1)
177
(dotimes-unrolled (i 16)
178
(setf x (aref accumulator i))
179
(dotimes-unrolled (j 8)
180
(setf b (logand (ash x (- j 7)) 1)
181
z0 (logxor z0 (aref key (+ (* i 8) j) b 0))
182
z1 (logxor z1 (aref key (+ (* i 8) j) b 1)))))
183
(setf (ub64ref/be accumulator 0) z0
184
(ub64ref/be accumulator 8) z1)))
187
(defun update-gmac (mac data &key (start 0) (end (length data)))
188
(declare (type (simple-array (unsigned-byte 8) (*)) data)
189
(type index start end)
190
(optimize (speed 3) (space 0) (safety 0) (debug 0)))
191
(let ((accumulator (gmac-accumulator mac))
193
(total-length (gmac-total-length mac))
194
(buffer (gmac-buffer mac))
195
(buffer-length (gmac-buffer-length mac))
196
(remaining (- end start)))
197
(declare (type (simple-array (unsigned-byte 8) (16)) accumulator buffer)
198
(type (unsigned-byte 64) total-length)
199
(type (integer 0 16) buffer-length)
200
(type index remaining))
202
;; Fill the buffer with new data if necessary
203
(when (plusp buffer-length)
204
(let ((n (min remaining (- 16 buffer-length))))
205
(declare (type (integer 0 16) n))
207
:start1 buffer-length
210
(incf buffer-length n)
214
;; Process the buffer
215
(when (= buffer-length 16)
216
(when #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
217
#-(and x86-64 ironclad-assembly) nil
218
(gmac-swap-16 buffer))
219
(xor-block 16 accumulator 0 buffer 0 accumulator 0)
220
(gmac-mul accumulator key)
221
(incf total-length 16)
222
(setf buffer-length 0))
225
(if #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
226
#-(and x86-64 ironclad-assembly) nil
227
(loop while (> remaining 16) do
228
(setf (ub64ref/le buffer 8) (ub64ref/be data start)
229
(ub64ref/le buffer 0) (ub64ref/be data (+ start 8)))
230
(xor-block 16 accumulator 0 buffer 0 accumulator 0)
231
(gmac-mul accumulator key)
232
(incf total-length 16)
235
(loop while (> remaining 16) do
236
(xor-block 16 accumulator 0 data start accumulator 0)
237
(gmac-mul accumulator key)
238
(incf total-length 16)
240
(decf remaining 16)))
242
;; Put the remaining data in the buffer
243
(when (plusp remaining)
244
(replace buffer data :start1 0 :start2 start :end2 end)
245
(setf buffer-length remaining))
248
(setf (gmac-total-length mac) total-length
249
(gmac-buffer-length mac) buffer-length)
252
(defun gmac-digest (mac &optional (encrypted-data-length 0))
253
(let ((accumulator (copy-seq (gmac-accumulator mac)))
255
(total-length (gmac-total-length mac))
256
(iv (copy-seq (gmac-iv mac)))
257
(buffer (copy-seq (gmac-buffer mac)))
258
(buffer-length (gmac-buffer-length mac)))
259
(declare (type (simple-array (unsigned-byte 8) (16)) accumulator buffer iv)
260
(type (unsigned-byte 64) total-length)
261
(type (integer 0 16) buffer-length))
263
;; Process the buffer
264
(when (plusp buffer-length)
265
(fill buffer 0 :start buffer-length)
266
(when #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
267
#-(and x86-64 ironclad-assembly) nil
268
(gmac-swap-16 buffer))
269
(xor-block 16 accumulator 0 buffer 0 accumulator 0)
270
(gmac-mul accumulator key)
271
(incf total-length buffer-length))
274
(if #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
275
#-(and x86-64 ironclad-assembly) nil
276
(setf (ub64ref/le buffer 0) (mod64* 8 encrypted-data-length)
277
(ub64ref/le buffer 8) (mod64* 8 (- total-length encrypted-data-length)))
278
(setf (ub64ref/be buffer 0) (mod64* 8 (- total-length encrypted-data-length))
279
(ub64ref/be buffer 8) (mod64* 8 encrypted-data-length)))
280
(xor-block 16 accumulator 0 buffer 0 accumulator 0)
281
(gmac-mul accumulator key)
284
(when #+(and x86-64 ironclad-assembly) (pclmulqdq-supported-p)
285
#-(and x86-64 ironclad-assembly) nil
286
(gmac-swap-16 accumulator))
287
(xor-block 16 accumulator 0 iv 0 accumulator 0)