Coverage report: /home/ellis/comp/ext/ironclad/src/ciphers/rc5.lisp
Kind | Covered | All | % |
expression | 0 | 202 | 0.0 |
branch | 0 | 6 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;;; rc5.lisp -- implementation of the RC5 encryption algorithm from RFC 2040
4
;;; RC5 is technically a parameterized cipher admitting a variable
5
;;; number of rounds. This implementation expose a method of selecting
6
;;; the number of rounds to be used (`n-rounds' &key parameter in
7
;;; CREATE-RC5-CONTEXT), but none of the upper-level machinery actually
8
;;; uses this parameter. In a small overhaul of the MAKE-CIPHER
9
;;; functionality in Ironclad, it would be nice to change this state of
10
;;; affairs. 12 was the number of rounds suggested initially, but RC5
11
;;; with 12 rounds is susceptible to a differential plaintext attack.
12
;;; OpenSSL supports 12 or 16 as the number of rounds (with no error
15
;;; See also the TODO file.
16
(defconstant +rc5/32-p+ #xb7e15163)
17
(defconstant +rc5/32-q+ #x9e3779b9)
19
(defconstant +rc5-w+ 32)
20
(defconstant +rc5-ww+ 4)
21
(defconstant +rc5-b+ 64)
22
(defconstant +rc5-bb+ 8)
24
(deftype rc5-n-rounds () '(mod 256))
25
(deftype rc5-round-keys () '(simple-array (unsigned-byte 32) (*)))
27
(defclass rc5 (cipher 8-byte-block-mixin)
28
((n-rounds :reader n-rounds :initarg :n-rounds :type rc5-n-rounds)
29
(round-keys :accessor round-keys
30
:type (simple-array (unsigned-byte 32) (*))))
31
(:default-initargs :n-rounds 12))
33
(define-block-encryptor rc5 8
34
(let ((n-rounds (n-rounds context))
35
(round-keys (round-keys context)))
36
(declare (type rc5-n-rounds n-rounds))
37
(declare (type rc5-round-keys round-keys))
38
(with-words ((a b) plaintext plaintext-start :big-endian nil)
39
(setf a (mod32+ a (aref round-keys 0))
40
b (mod32+ b (aref round-keys 1)))
43
(store-words ciphertext ciphertext-start a b))
45
(setf a (mod32+ (rol32 a (mod b 32)) (aref round-keys (* i 2))))
47
(setf b (mod32+ (rol32 b (mod a 32)) (aref round-keys (1+ (* i 2)))))))))
49
(define-block-decryptor rc5 8
50
(let ((n-rounds (n-rounds context))
51
(round-keys (round-keys context)))
52
(declare (type rc5-n-rounds n-rounds))
53
(declare (type rc5-round-keys round-keys))
54
(with-words ((a b) ciphertext ciphertext-start :big-endian nil)
55
(do ((i n-rounds (1- i)))
57
(setf b (mod32- b (aref round-keys 1))
58
a (mod32- a (aref round-keys 0)))
59
(store-words plaintext plaintext-start a b))
60
(setf b (rol32 (mod32- b (aref round-keys (1+ (* i 2))))
61
(mod (- 32 (mod a 32)) 32)))
63
(setf a (rol32 (mod32- a (aref round-keys (* i 2)))
64
(mod (- 32 (mod b 32)) 32)))
65
(setf a (logxor a b))))))
67
(defun rc5-expand-key (key n-rounds)
68
(declare (type (simple-array (unsigned-byte 8) (*)) key))
69
(declare (type rc5-n-rounds n-rounds))
70
(let* ((n-round-keys (* 2 (1+ n-rounds)))
71
(round-keys (make-array n-round-keys :element-type '(unsigned-byte 32)))
72
(expanded-key (make-array 256 :element-type '(unsigned-byte 8)
74
(n-expanded-key-words (ceiling (length key) 4))
75
(l (make-array 64 :element-type '(unsigned-byte 32))))
76
(declare (dynamic-extent expanded-key l))
77
(declare (type (simple-array (unsigned-byte 8) (256)) expanded-key))
78
(declare (type (simple-array (unsigned-byte 32) (64)) l))
79
(declare (type (simple-array (unsigned-byte 32) (*)) round-keys))
80
;; convert the key into a sequence of (unsigned-byte 32). this way
81
;; is somewhat slow and consy, but it's easily shown to be correct.
82
(replace expanded-key key)
83
(loop for i from 0 below 64 do
84
(setf (aref l i) (ub32ref/le expanded-key (* i 4))))
85
;; initialize the round keys
86
(loop initially (setf (aref round-keys 0) +rc5/32-p+)
87
for i from 1 below n-round-keys do
88
(setf (aref round-keys i) (mod32+ (aref round-keys (1- i)) +rc5/32-q+)))
89
;; mix in the user's key
90
(do ((k (* 3 (max n-expanded-key-words n-round-keys)) (1- k))
93
(i 0 (mod (1+ i) n-round-keys))
94
(j 0 (mod (1+ j) n-expanded-key-words)))
96
(declare (type (unsigned-byte 32) a b))
97
(setf a (rol32 (mod32+ (aref round-keys i) (mod32+ a b)) 3))
98
(setf (aref round-keys i) a)
99
(setf b (let ((x (mod32+ a b)))
100
(declare (type (unsigned-byte 32) x))
101
(rol32 (mod32+ (aref l j) x) (mod x 32))))
102
(setf (aref l j) b))))
104
(defmethod schedule-key ((cipher rc5) key)
105
(let* ((n-rounds (n-rounds cipher))
106
(round-keys (rc5-expand-key key n-rounds)))
107
(setf (round-keys cipher) round-keys)
111
(:encrypt-function rc5-encrypt-block)
112
(:decrypt-function rc5-decrypt-block)
114
(:key-length (:variable 1 255 1)))