summaryrefslogtreecommitdiff
path: root/src/eris-decode.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/eris-decode.lisp')
-rw-r--r--src/eris-decode.lisp62
1 files changed, 31 insertions, 31 deletions
diff --git a/src/eris-decode.lisp b/src/eris-decode.lisp
index b3629a2..df64913 100644
--- a/src/eris-decode.lisp
+++ b/src/eris-decode.lisp
@@ -20,19 +20,19 @@
fetched blocks are what they claim to be. Only disable this if the blocks are
fetched from a trusted party.")
-(defmacro hash-check (block hash)
+(defmacro hash-check (block rk &optional key)
`(when *decode-safety-checks*
(let ((hash (ironclad:digest-sequence :blake2/256 ,block)))
- (unless (equalp ,hash hash)
- (error 'hash-mismatch :reference ,hash :hash hash )))))
+ (unless (octet-vector= ,rk hash ,(if key :start1 :end1) 32)
+ (error 'hash-mismatch :reference ,rk :hash hash )))))
+;; This is quite pointless.
(defmacro execute-fetch-function (fetch-function &rest args)
- `(restart-case (funcall ,fetch-function ,@args)
+ `(restart-case (funcall ,fetch-function (subseq ,@args 0 32))
(use-value (value) value)))
(defun key-reference-null? (kr)
- (and (equalp (reference kr) null-secret)
- (equalp (key kr) null-secret)))
+ (octet-vector= kr #.(make-array 64 :element-type 'octet :initial-element 0)))
(defclass high-block ()
((data :initarg :data :accessor data :type octet-vector)
@@ -89,15 +89,16 @@ represents."
;; The standard states that:
;; "If 64 bytes of zeroes are encountered the rest of the node MUST be checked to be all zeroes"
;; This procedure processes the block from right to left so it's not really applicable here
+ ;; A maliciously crafted ERIS block which contains 0 ... kr ... 0 ... kr could fool this.
(flet ((find-last-reference (block)
(loop for i from (1- (/ block-size 64)) downto 0
- for key-reference = (octets-to-reference-pair block (* 64 i))
+ for key-reference = (subseq block (* 64 i) (+ 64 (* 64 i)))
unless (key-reference-null? key-reference)
return (values key-reference i))))
(loop with position = 0
for local-level = level then (1- local-level)
- for block = root then (funcall get-block (reference key-reference) (key key-reference) (make-nonce local-level))
+ for block = root then (funcall get-block key-reference (make-nonce local-level))
for (key-reference block-pos) = (multiple-value-list (find-last-reference block))
if (eql 0 local-level)
do (setf position (+ position (unpad-block block)))
@@ -126,11 +127,11 @@ it is necessary and sets the position in the buffer to 0."
(type fixnum next-pos))
(when (zerop next-pos) ;; if 1+ mod blocks results in a zero, then update the next block
(process-block (cdr blocks) mod (1+ level)))
- (let ((kr (octets-to-reference-pair
- (data (cadr blocks))
- (the fixnum (* next-pos 64)))))
+ (let ((kr (let ((a (make-octet-vector 64)))
+ (replace a (data (cadr blocks)) :start2 (the fixnum (* next-pos 64)))
+ a)))
(setf (data current)
- (funcall get-block (reference kr) (key kr) (svref nonce-array level)))))))
+ (funcall get-block kr (svref nonce-array level)))))))
(process-block (reverse root) (/ block-size 64) 0) ;; process the blocks from level 0 up
;; setf the buffer data to the level 0 block
(setf (data buffer) (data (car (last root)))
@@ -184,12 +185,12 @@ it is necessary and sets the position in the buffer to 0."
do (error 'eof :eof new-pos :position (pos stream))
until (eq nil (cdr blocks))
when (or update-tree (not (eq block-position (pos lower-block))))
- do (let ((rk (octets-to-reference-pair
- (data (car blocks))
- (* 64 block-position))))
+ do (let ((rk (let ((a (make-octet-vector 64)))
+ (replace a (data (car blocks)) :start2 (* 64 block-position))
+ a)))
(when (key-reference-null? rk)
(error 'eof :eof new-pos :position (pos stream)))
- (setf (data lower-block) (funcall get-block (reference rk) (key rk) (svref nonce-array (1- level)))
+ (setf (data lower-block) (funcall get-block rk (svref nonce-array (1- level)))
(pos lower-block) block-position
update-tree t))
finally (when update-tree ;; if anything changed
@@ -232,22 +233,22 @@ FETCH-FUNCTION is not handled."
(cached-lambda (:cache-class 'lru-cache
:capacity cache-capacity
:table (make-hash-table :size (1+ cache-capacity) :test #'equalp))
- (reference key nonce)
- (declare (type octet-vector reference key nonce))
- (let ((block (execute-fetch-function fetch-function reference)))
+ (rk nonce)
+ (declare (type octet-vector rk nonce))
+ (let ((block (execute-fetch-function fetch-function rk)))
(declare (type octet-vector block))
- (hash-check block reference)
- (decrypt-block block key nonce)))
- (lambda (reference key nonce)
- (declare (type octet-vector reference key nonce))
- (let ((block (execute-fetch-function fetch-function reference)))
+ (hash-check block rk)
+ (decrypt-block block rk nonce)))
+ (lambda (rk nonce)
+ (declare (type octet-vector rk nonce))
+ (let ((block (execute-fetch-function fetch-function rk)))
(declare (type octet-vector block))
- (hash-check block reference)
- (decrypt-block block key nonce)))))
- (root (funcall get-block (reference root-reference-pair) (key root-reference-pair) (make-nonce level))))
+ (hash-check block rk)
+ (decrypt-block block rk nonce)))))
+ (root (funcall get-block root-reference-pair (make-nonce level))))
;; "Implementations MUST verify the key appearing in the read capability
;; if level of encoded content is larger than 0."
- (when (> level 0) (hash-check root (key root-reference-pair)))
+ (when (> level 0) (hash-check root root-reference-pair :key))
(case level
;; Treat level 0 blocks specially, since those are just a single buffer.
(0 (let ((stream
@@ -256,9 +257,8 @@ FETCH-FUNCTION is not handled."
:data (make-array block-size :element-type 'octet)
:pos 0
:eof -1)
- :get-block (lambda (reference key)
- (declare (ignore key))
- (error 'missing-block :reference reference))
+ :get-block (lambda (rk)
+ (error 'missing-block :reference rk))
:block-size block-size
:root nil
:eof (find-eof root get-block block-size level)