1;;;; -*- mode: lisp; indent-tabs-mode: nil -*- 2;;;; skein-mac.lisp -- implementation of the Skein MAC 3 4(in-package :crypto) 5 6 7(defclass skein-mac (mac) 8 ((value :accessor skein-value :initarg :value) 9 (tweak :accessor skein-tweak :initarg :tweak) 10 (cfg :accessor skein-cfg :initarg :cfg) 11 (buffer :accessor skein-buffer :initarg :buffer) 12 (buffer-length :accessor skein-buffer-length :initarg :buffer-length) 13 (cipher :accessor skein-cipher :initarg :cipher) 14 (block-length :accessor block-length :initarg :block-length) 15 (digest-length :accessor digest-length :initarg :digest-length))) 16 17(defun make-skein-mac (key &key (block-length 64) (digest-length 64)) 18 (unless (or (= block-length 32) 19 (= block-length 64) 20 (= block-length 128)) 21 (error 'invalid-mac-parameter 22 :mac-name 'skein-mac 23 :message "The block length must be 32, 64 or 128 bytes")) 24 25 (make-instance 'skein-mac 26 :key key 27 :block-length block-length 28 :digest-length digest-length)) 29 30(defmethod copy-skein-mac ((mac skein-mac) &optional copy) 31 (declare (type (or null skein-mac) copy)) 32 (let ((copy (if copy 33 copy 34 (make-instance 'skein-mac 35 :key (skein-value mac) 36 :block-length (block-length mac) 37 :digest-length (digest-length mac))))) 38 (declare (type skein-mac copy)) 39 (replace (skein-value copy) (skein-value mac)) 40 (replace (skein-tweak copy) (skein-tweak mac)) 41 (replace (skein-cfg copy) (skein-cfg mac)) 42 (replace (skein-buffer copy) (skein-buffer mac)) 43 (setf (skein-buffer-length copy) (skein-buffer-length mac)) 44 (setf (skein-cipher copy) (skein-copy-cipher (skein-cipher mac))) 45 copy)) 46 47(defmethod shared-initialize :after ((mac skein-mac) slot-names 48 &rest initargs 49 &key key &allow-other-keys) 50 (declare (ignore slot-names initargs) 51 (type (simple-array (unsigned-byte 8) (*)) key)) 52 (let* ((block-length (block-length mac)) 53 (digest-length (digest-length mac)) 54 (value (make-array block-length 55 :element-type '(unsigned-byte 8) 56 :initial-element 0)) 57 (tweak (skein-make-tweak t nil +skein-key+ 0)) 58 (cfg (skein-make-configuration-string (* 8 digest-length))) 59 (cipher (ecase block-length 60 (32 (make-cipher :threefish256 61 :key value 62 :mode :ecb)) 63 (64 (make-cipher :threefish512 64 :key value 65 :mode :ecb)) 66 (128 (make-cipher :threefish1024 67 :key value 68 :mode :ecb))))) 69 (setf (skein-cipher mac) cipher 70 (skein-value mac) value 71 (skein-cfg mac) cfg 72 (skein-tweak mac) tweak 73 (skein-buffer mac) (make-array block-length 74 :element-type '(unsigned-byte 8)) 75 (skein-buffer-length mac) 0) 76 77 ;; Process key 78 (when (plusp (length key)) 79 (skein-ubi mac key 0 (length key)) 80 (let* ((padding-length (- block-length (skein-buffer-length mac))) 81 (padding (make-array padding-length 82 :element-type '(unsigned-byte 8) 83 :initial-element 0))) 84 (skein-update-tweak tweak 85 :final t 86 :position-increment (skein-buffer-length mac)) 87 (skein-ubi mac padding 0 padding-length t))) 88 89 ;; Process configuration string 90 (let ((padded-cfg (make-array block-length 91 :element-type '(unsigned-byte 8) 92 :initial-element 0))) 93 (replace padded-cfg cfg :end2 32) 94 (skein-update-tweak tweak 95 :first t 96 :final t 97 :type +skein-cfg+ 98 :position 32) 99 (skein-ubi mac padded-cfg 0 block-length t)) 100 101 ;; Prepare message processing 102 (skein-update-tweak tweak 103 :first t 104 :final nil 105 :type +skein-msg+ 106 :position 0))) 107 108(defun update-skein-mac (mac sequence &key (start 0) end) 109 (skein-ubi mac sequence start (or end (length sequence))) 110 mac) 111 112(defun skein-mac-digest (mac) 113 (let ((digest (make-array (digest-length mac) 114 :element-type '(unsigned-byte 8))) 115 (mac-copy (copy-skein-mac mac))) 116 (skein-finalize mac-copy digest 0) 117 digest)) 118 119(defmac skein-mac 120 make-skein-mac 121 update-skein-mac 122 skein-mac-digest) 123