Coverage report: /home/ellis/comp/ext/ironclad/src/macs/cmac.lisp

KindCoveredAll%
expression0246 0.0
branch014 0.0
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;; cmac.lisp -- The CMAC algorithm from NIST 800-38B.
2
 (in-package :crypto)
3
 
4
 (defclass cmac (mac)
5
   ((cipher :reader cmac-cipher :initarg :cipher)
6
    (subkey1 :reader cmac-subkey1 :initarg :subkey1
7
             :type (simple-array (unsigned-byte 8) (*)))
8
    (subkey2 :reader cmac-subkey2 :initarg :subkey2
9
             :type (simple-array (unsigned-byte 8) (*)))
10
    (buffer :reader cmac-buffer :initarg :buffer
11
            :type (simple-array (unsigned-byte 8) (*)))
12
    (buffer-index :accessor cmac-buffer-index :initform 0 :type index)))
13
 
14
 (defun make-cmac (key cipher-name)
15
   (declare (type (simple-array (unsigned-byte 8) (*)) key))
16
   (let* ((cipher (make-cipher cipher-name :key key :mode :ecb))
17
          (block-length (block-length cipher-name))
18
          (L (make-array block-length :element-type '(unsigned-byte 8)
19
                         :initial-element 0)))
20
     (encrypt-in-place cipher L)
21
     (flet ((gen-subkey (b)
22
              (let* ((n-bits (* block-length 8))
23
                     (k (integer-to-octets
24
                         (ldb (byte n-bits 0) (ash (octets-to-integer b) 1))
25
                         :n-bits n-bits)))
26
                (when (logbitp 7 (aref b 0))
27
                  (ecase block-length
28
                    (8 (setf (aref k 7) (logxor (aref k 7) #x1b)))
29
                    (16 (setf (aref k 15) (logxor (aref k 15) #x87)))
30
                    (32 (setf (aref k 30) (logxor (aref k 30) #x4)
31
                              (aref k 31) (logxor (aref k 31) #x25)))
32
                    (64 (setf (aref k 62) (logxor (aref k 62) #x1)
33
                              (aref k 63) (logxor (aref k 63) #x25)))
34
                    (128 (setf (aref k 125) (logxor (aref k 125) #x8)
35
                               (aref k 126) (logxor (aref k 126) #x0)
36
                               (aref k 127) (logxor (aref k 127) #x43)))))
37
                k)))
38
       (let ((L.u (gen-subkey L)))
39
         (make-instance 'cmac
40
                        :cipher cipher
41
                        :subkey1 L.u
42
                        :subkey2 (gen-subkey L.u)
43
                        :buffer (make-array block-length
44
                                            :element-type '(unsigned-byte 8)
45
                                            :initial-element 0))))))
46
 
47
 (defmethod reinitialize-instance ((mac cmac) &rest initargs
48
                                   &key key &allow-other-keys)
49
   (declare (ignore initargs)
50
            (type (simple-array (unsigned-byte 8) (*)) key))
51
   (fill (cmac-buffer mac) 0)
52
   (setf (cmac-buffer-index mac) 0)
53
   (reinitialize-instance (cmac-cipher mac) :key key :mode :ecb)
54
   mac)
55
 
56
 (defun update-cmac (cmac sequence &key (start 0) (end (length sequence)))
57
   (declare (type (simple-array (unsigned-byte 8) (*)) sequence)
58
            (type index start end)
59
            (optimize (speed 3) (space 0) (safety 0) (debug 0)))
60
   (let* ((cipher (cmac-cipher cmac))
61
          (encryption-function (encrypt-function cipher))
62
          (buffer (cmac-buffer cmac))
63
          (buffer-index (cmac-buffer-index cmac))
64
          (block-length (length buffer))
65
          (remaining (- end start)))
66
     (declare (type (simple-array (unsigned-byte 8) (*)) buffer))
67
 
68
     (when (< 0 buffer-index block-length)
69
       (dotimes (i (min remaining (- block-length buffer-index)))
70
         (setf (aref buffer buffer-index) (logxor (aref buffer buffer-index)
71
                                                  (aref sequence start)))
72
         (incf buffer-index)
73
         (incf start)
74
         (decf remaining)))
75
 
76
     (when (and (= buffer-index block-length)
77
                (plusp remaining))
78
       (funcall encryption-function cipher buffer 0 buffer 0)
79
       (setf buffer-index 0))
80
 
81
     (loop while (> remaining block-length) do
82
       (xor-block block-length buffer 0 sequence start buffer 0)
83
       (funcall encryption-function cipher buffer 0 buffer 0)
84
       (incf start block-length)
85
       (decf remaining block-length))
86
 
87
     (loop while (plusp remaining) do
88
       (setf (aref buffer buffer-index) (logxor (aref buffer buffer-index)
89
                                                (aref sequence start)))
90
       (incf buffer-index)
91
       (incf start)
92
       (decf remaining))
93
 
94
     (setf (cmac-buffer-index cmac) buffer-index)
95
     (values)))
96
 
97
 (defun cmac-digest (cmac)
98
   (let* ((block-length (length (cmac-buffer cmac)))
99
          (x (copy-seq (cmac-buffer cmac)))
100
          (L (cond
101
               ((= block-length (cmac-buffer-index cmac))
102
                (cmac-subkey1 cmac))
103
               (t
104
                (setf (aref x (cmac-buffer-index cmac))
105
                      (logxor (aref x (cmac-buffer-index cmac)) #x80))
106
                (cmac-subkey2 cmac)))))
107
     (xor-block block-length L 0 x 0 x 0)
108
     (encrypt-in-place (cmac-cipher cmac) x)
109
     x))
110
 
111
 (defmac cmac
112
         make-cmac
113
         update-cmac
114
         cmac-digest)