Coverage report: /home/ellis/comp/ext/ironclad/src/kdf/pkcs5.lisp

KindCoveredAll%
expression0168 0.0
branch014 0.0
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;;; pkcs5.lisp
2
 (in-package :crypto)
3
 
4
 ;;; PBKDF1 from RFC 2898, section 5.1
5
 (defclass pbkdf1 ()
6
   ((digest :reader kdf-digest)))
7
 
8
 (defmethod shared-initialize :after ((kdf pbkdf1) slot-names &rest initargs
9
                                      &key digest &allow-other-keys)
10
   (declare (ignore slot-names initargs))
11
   (let ((digest-name (massage-symbol digest)))
12
     (cond
13
       ;; Permit DIGEST to be NULL to indicate reinitializing the whole
14
       ;; instance.
15
       ((null digest)
16
        (reinitialize-instance (kdf-digest kdf)))
17
       ((not (digestp digest-name))
18
        (error 'unsupported-digest :name digest-name))
19
       ;; Don't cons unnecessarily.  (Although this depends how expensive
20
       ;; TYPEP is with a non-constant type...)
21
       ((and (slot-boundp kdf 'digest)
22
             (typep (digest kdf) digest-name))
23
        (reinitialize-instance (kdf-digest kdf)))
24
       ((member digest-name '(md2 md5 sha1))
25
        (setf (slot-value kdf 'digest)
26
              (funcall (the function (get digest-name '%make-digest)))))
27
       (t
28
        (error 'ironclad-error
29
               :format-control "Digest ~A not supported for PBKDF1"
30
               :format-arguments (list digest))))
31
     kdf))
32
 
33
 (defmethod derive-key ((kdf pbkdf1) passphrase salt iteration-count key-length)
34
   (check-type iteration-count (integer 1 *))
35
   (check-type key-length (integer 1 *))
36
   (loop with digest = (kdf-digest kdf)
37
      with digest-length = (digest-length digest)
38
      with key = (make-array 20 :element-type '(unsigned-byte 8))
39
      initially
40
        (update-digest digest passphrase)
41
        (update-digest digest salt)
42
        (produce-digest digest :digest key)
43
      for i from 1 below iteration-count
44
      do
45
        (reinitialize-instance digest)
46
        (update-digest digest key :end digest-length)
47
        (produce-digest digest :digest key)
48
      finally
49
        (return (subseq key 0 (min key-length (length key))))))
50
 
51
 ;;; PBKDF2, from RFC 2898, section 5.2
52
 (defclass pbkdf2 ()
53
   ((digest-name :initarg :digest :reader kdf-digest)))
54
 
55
 (defun pbkdf2-derive-key (digest passphrase salt iteration-count key-length)
56
   (check-type iteration-count (integer 1 *))
57
   (check-type key-length (integer 1 *))
58
   (loop with count = 1
59
      with hmac = (make-hmac passphrase digest)
60
      with hmac-length = (digest-length digest)
61
      with key = (make-array key-length :element-type '(unsigned-byte 8)
62
                             :initial-element 0)
63
      with key-position = 0
64
      with count-buffer = (make-array 4 :element-type '(unsigned-byte 8))
65
      with hmac-out = (make-array hmac-length :element-type '(unsigned-byte 8))
66
      while (plusp key-length)
67
      do (let ((size (min hmac-length key-length)))
68
           (reinitialize-instance hmac :key passphrase)
69
           (update-hmac hmac salt)
70
           (setf (ub32ref/be count-buffer 0) count)
71
           (update-hmac hmac count-buffer)
72
           (hmac-digest hmac :buffer hmac-out)
73
           (xor-block size hmac-out 0 key key-position key key-position)
74
           (loop for i from 1 below iteration-count
75
              do
76
                (reinitialize-instance hmac :key passphrase)
77
                (update-hmac hmac hmac-out)
78
                (hmac-digest hmac :buffer hmac-out)
79
                (xor-block size hmac-out 0 key key-position key key-position)
80
              finally
81
                (decf key-length size)
82
                (incf key-position size)
83
                (incf count)))
84
      finally (return key)))
85
 
86
 (defmethod derive-key ((kdf pbkdf2) passphrase salt iteration-count key-length)
87
   (pbkdf2-derive-key (kdf-digest kdf) passphrase salt iteration-count key-length))