Coverage report: /home/ellis/comp/ext/ironclad/src/util.lisp
Kind | Covered | All | % |
expression | 83 | 125 | 66.4 |
branch | 1 | 4 | 25.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;;; util.lisp -- functions that come in handy in crypto applications
4
(defun byte-array-to-hex-string (vector &key (start 0) end (element-type 'base-char))
5
"Return a string containing the hexadecimal representation of the
6
subsequence of VECTOR between START and END. ELEMENT-TYPE controls
7
the element-type of the returned string."
8
(declare (type (vector (unsigned-byte 8)) vector)
10
(type (or null fixnum) end)
11
(optimize (speed 3) (safety 1)))
12
(let* ((end (or end (length vector)))
13
(length (- end start))
14
(hexdigits (load-time-value (coerce "0123456789abcdef" 'simple-base-string) t)))
15
(loop with string = (ecase element-type
16
;; so that the compiler optimization can jump in
17
(base-char (make-string (* length 2)
18
:element-type 'base-char))
19
(character (make-string (* length 2)
20
:element-type 'character)))
21
for i from start below end
22
for j from 0 below (* length 2) by 2
23
do (let ((byte (aref vector i)))
25
(aref hexdigits (ldb (byte 4 4) byte))
27
(aref hexdigits (ldb (byte 4 0) byte))))
28
finally (return string))))
30
(defun hex-string-to-byte-array (string &key (start 0) (end nil))
31
"Parses a substring of STRING delimited by START and END of
32
hexadecimal digits into a byte array."
33
(declare (type string string))
34
(let* ((end (or end (length string)))
35
(length (/ (- end start) 2))
36
(key (make-array length :element-type '(unsigned-byte 8))))
37
(declare (type (simple-array (unsigned-byte 8) (*)) key))
38
(flet ((char-to-digit (char)
39
(or (digit-char-p char 16)
40
(error 'ironclad-error
41
:format-control "~A is not a hex digit"
42
:format-arguments (list char)))))
44
for j from start below end by 2
46
(+ (* (char-to-digit (char string j)) 16)
47
(char-to-digit (char string (1+ j)))))
48
finally (return key)))))
50
(defun ascii-string-to-byte-array (string &key (start 0) end)
51
"Convert STRING to a (VECTOR (UNSIGNED-BYTE 8)). It is an error if
52
STRING contains any character whose CHAR-CODE is greater than 255."
53
(declare (type string string)
55
(type (or null fixnum) end)
56
(optimize (speed 3) (safety 1)))
57
(let* ((length (length string))
58
(vec (make-array length :element-type '(unsigned-byte 8)))
59
(end (or end length)))
60
(loop for i from start below end do
61
(let ((byte (char-code (char string i))))
63
(error 'ironclad-error
64
:format-control "~A is not an ASCII character"
65
:format-arguments (list (char string i))))
66
(setf (aref vec i) byte))
67
finally (return vec))))
69
(defun constant-time-equal (data1 data2)
70
"Returns T if the elements in DATA1 and DATA2 are identical, NIL otherwise.
71
All the elements of DATA1 and DATA2 are compared to prevent timing attacks."
72
(declare (type (simple-array (unsigned-byte 8) (*)) data1 data2)
74
(let ((res (if (= (length data1) (length data2)) 0 1)))
75
(declare (type (unsigned-byte 8) res))
76
(loop for d1 across data1
78
do (setf res (logior res (logxor d1 d2))))