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

KindCoveredAll%
expression0222 0.0
branch00nil
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;;; scrypt.lisp
2
 (in-package :crypto)
3
 
4
 ;;; scrypt from Colin Percival's
5
 ;;; "Stronger Key Derivation via Sequential Memory-Hard Functions"
6
 ;;; presented at BSDCan'09, May 2009.
7
 ;;; http://www.tarsnap.com/scrypt.html
8
 (defclass scrypt-kdf ()
9
  ((n :initarg :n :reader scrypt-kdf-N)
10
   (r :initarg :r :reader scrypt-kdf-r)
11
   (p :initarg :p :reader scrypt-kdf-p)))
12
 
13
 (defun scrypt-vector-salsa (b)
14
   (declare (type (simple-octet-vector 64) b))
15
   (let ((x (make-array 16 :element-type '(unsigned-byte 32))))
16
     (declare (type (simple-array (unsigned-byte 32) (16)) x))
17
     (declare (dynamic-extent x))
18
     (fill-block-ub8-le x b 0)
19
     (salsa20/8-core b x)))
20
 
21
 (defun block-mix (b xy xy-start r)
22
   (declare (type (simple-array (unsigned-byte 8) (*)) b xy))
23
   ;; The derivation of the bound here is that (* I 64) in the first loop below
24
   ;; must be a legitimate array index.  That loop runs to (* 2 R), hence the
25
   ;; truncation by 128.  The subtraction of 64 comes from loops further down.
26
   (declare (type (integer 0 (#.(truncate (- array-dimension-limit 64) 128))) r))
27
   (let ((xs (make-array 64 :element-type '(unsigned-byte 8))))
28
     (declare (type (simple-array (unsigned-byte 8) (64)) xs))
29
     (declare (dynamic-extent xs))
30
     (replace xs b :start2 (* 64 (1- (* 2 r))) :end1 64)
31
     (dotimes (i (* 2 r))
32
       (xor-block 64 xs 0 b (* i 64) xs 0)
33
       (scrypt-vector-salsa xs)
34
       (replace xy xs :start1 (+ xy-start (* i 64)) :end2 64))
35
     (dotimes (i r)
36
       (replace b xy :start1 (* i 64) :end1 (+ 64 (* i 64)) :start2 (+ xy-start (* 64 2 i))))
37
     (dotimes (i r)
38
       (replace b xy :start1 (* 64 (+ i r)) :end1 (+ (* 64 (+ i r)) 64) :start2 (+ xy-start (* 64 (1+ (* i 2))))))))
39
 
40
 (defun smix (b b-start r N v xy)
41
   (declare (type (simple-array (unsigned-byte 8) (*)) b v xy))
42
   (declare (type (integer 0 (#.(truncate array-dimension-limit 128))) r))
43
   (let ((x xy)
44
         (xy-start (* 128 r))
45
         (smix-length (* 128 r)))
46
     (replace x b :end1 smix-length :start2 b-start)
47
     (dotimes (i N)
48
       (replace v x :start1 (* i smix-length) :end2 smix-length)
49
       (block-mix x xy xy-start r))
50
     (dotimes (i N)
51
       (let ((j (ldb (byte 32 0) (logand (ub64ref/le x (* (1- (* 2 r)) 64)) (1- N)))))
52
         (xor-block smix-length x 0 v (* j smix-length) x 0)
53
         (block-mix x xy xy-start r)))
54
     (replace b x :start1 b-start :end1 (+ b-start smix-length))))
55
 
56
 (defmethod derive-key ((kdf scrypt-kdf) passphrase salt iteration-count key-length)
57
   (declare (ignore iteration-count))
58
   (let* ((pb-kdf (make-kdf 'pbkdf2 :digest 'sha256))
59
          (xy (make-array (* 256 (scrypt-kdf-r kdf)) :element-type '(unsigned-byte 8)))
60
          (v (make-array (* 128 (scrypt-kdf-r kdf) (scrypt-kdf-N kdf)) :element-type '(unsigned-byte 8)))
61
          (b (derive-key pb-kdf passphrase salt 1 (* (scrypt-kdf-p kdf) 128 (scrypt-kdf-r kdf)))))
62
     (dotimes (i (scrypt-kdf-p kdf))
63
       (smix b (* i 128 (scrypt-kdf-r kdf)) (scrypt-kdf-r kdf) (scrypt-kdf-N kdf) v xy))
64
     (reinitialize-instance pb-kdf :digest 'sha256)
65
     (derive-key pb-kdf passphrase b 1 key-length)))