;;;; message-digest-primitive.scm -*- Scheme -*- ;;;; Kon Lovett, Apr '20 ;;;; Kon Lovett, Jul '18 ;;;; Kon Lovett, Aug '17 ;;;; Kon Lovett, Apr '12 ;;;; Kon Lovett, May '10 (message-digest.scm) ;;;; Kon Lovett, Jan '06 (message-digest.scm) ;; Issues ;; ;; - see tiger-hash , sha2 , sha1 , ripemd , md5 , hashes ;; ;; - synthesize raw-update from update (module message-digest-primitive (;export ; message-digest-primitive make-message-digest-primitive-context ; Algorithm API make-message-digest-primitive message-digest-primitive? check-message-digest-primitive error-message-digest-primitive message-digest-primitive-name message-digest-primitive-block-length message-digest-primitive-context-info message-digest-primitive-digest-length message-digest-primitive-init message-digest-primitive-update message-digest-primitive-final message-digest-primitive-raw-update) (import scheme) (import (chicken base)) (import (chicken fixnum)) (import (chicken gc)) (import (chicken type)) (import (chicken foreign)) (import (only (chicken memory) allocate free)) (import (only type-checks define-check+error-type check-positive-fixnum check-procedure)) (import (only type-errors error-argument-type)) ;;; Support ;; (include "message-digest-primitive.types") (define-type primitive-name (or symbol string)) (define-type init-procedure ((not immediate) -> *)) (define-type update-procedure ((not immediate) (not immediate) fixnum -> *)) (define-type final-procedure ((not immediate) (not immediate) -> *)) (define-type context-info (or fixnum procedure)) (define-type raw-update-value (or boolean update-procedure)) ;; (define (positive-fixnum? obj) (and (fixnum? obj) (positive? obj))) (define (primitive-context-info? obj) (or (procedure? obj) (positive-fixnum? obj))) (define (primitive-name? obj) (or (symbol? obj) (string? obj))) ;;; Message Digest Algorithm API ;; ;assignment of value of type `(procedure ;message-digest-primitive#*make-message-digest-primitive (* * * * * * * *) ;(struct message-digest-primitive#message-digest-primitive))' to toplevel ;variable `message-digest-primitive#*make-message-digest-primitive' does not ;match declared type `(procedure ;message-digest-primitive#*make-message-digest-primitive ((or fixnum procedure) ;fixnum procedure procedure procedure fixnum (or symbol string) (or boolean ;procedure)) (struct message-digest-primitive))' (: *make-message-digest-primitive (context-info fixnum init-procedure update-procedure final-procedure fixnum primitive-name raw-update-value -> message-digest-primitive)) (: message-digest-primitive? (* -> boolean : message-digest-primitive)) (: message-digest-primitive-context-info (message-digest-primitive --> context-info)) (: message-digest-primitive-digest-length (message-digest-primitive --> fixnum)) (: message-digest-primitive-init (message-digest-primitive --> init-procedure)) (: message-digest-primitive-update (message-digest-primitive --> update-procedure)) (: message-digest-primitive-final (message-digest-primitive --> final-procedure)) (: message-digest-primitive-block-length (message-digest-primitive --> fixnum)) (: message-digest-primitive-name (message-digest-primitive --> primitive-name)) (: message-digest-primitive-raw-update (message-digest-primitive --> raw-update-value)) ; (define-record-type message-digest-primitive (*make-message-digest-primitive ctxi digest-len init update final block-len name raw-update) message-digest-primitive? (ctxi message-digest-primitive-context-info) (digest-len message-digest-primitive-digest-length) (init message-digest-primitive-init) (update message-digest-primitive-update) (final message-digest-primitive-final) (block-len message-digest-primitive-block-length) (name message-digest-primitive-name) (raw-update message-digest-primitive-raw-update) ) (define-check+error-type message-digest-primitive) ;; (define-inline (check-message-digest-arguments loc ctx-info digest-len init update final block-len name raw-update) (unless (primitive-context-info? ctx-info) (error-argument-type loc ctx-info "positive-fixnum or procedure" 'context-info) ) (check-positive-fixnum loc digest-len 'digest-length) (check-procedure loc init 'digest-initializer) (when update (check-procedure loc update 'digest-updater) ) (check-procedure loc final 'digest-finalizer) (check-positive-fixnum loc block-len 'block-length) (unless (primitive-name? name) (error-argument-type loc name "symbol or string" 'name) ) (when raw-update (check-procedure loc raw-update 'digest-raw-updater) ) ) ;; (: scheme-object-data-pointer ((not immediate) -> pointer)) ; (define scheme-object-data-pointer (foreign-lambda* c-pointer ((scheme-pointer psrc)) "return( psrc );")) ;; (: make-scheme-object-updater (update-procedure -> update-procedure)) ; (define ((make-scheme-object-updater raw-update) ctx-info obj len) (raw-update ctx-info (scheme-object-data-pointer obj) len) ) ;; ;assignment of value of type `(procedure message-digest-primitive#make-message-digest-primitive (* * * * * #!rest) (struct message-digest-primitive#message-digest-primitive))' to toplevel variable `message-digest-primitive#make-message-digest-primitive' does not match declared type `(procedure message-digest-primitive#make-message-digest-primitive ((or fixnum procedure) fixnum procedure procedure procedure #!rest *) (struct message-digest-primitive))' (: make-message-digest-primitive (context-info fixnum init-procedure (or boolean update-procedure) final-procedure #!rest -> message-digest-primitive)) ; (define (make-message-digest-primitive ctx-info digest-len init update final #!key (block-length 4) (name (gensym 'mdp)) (raw-update #f)) (check-message-digest-arguments 'make-message-digest-primitive ctx-info digest-len init update final block-length name raw-update) (let ( (update (or update (and raw-update (make-scheme-object-updater raw-update)))) ) ;we know about raw -> cooked (unless update (error 'make-message-digest-primitive "missing update & raw-update") ) (*make-message-digest-primitive ctx-info digest-len init update final block-length name raw-update) ) ) ;; (: make-message-digest-primitive-context (message-digest-primitive -> message-digest-primitive-context)) ; (define (make-message-digest-primitive-context mdp) (let ( (ctx-info (message-digest-primitive-context-info (check-message-digest-primitive 'make-message-digest-primitive-context mdp))) ) (if (procedure? ctx-info) (ctx-info) (set-finalizer! (allocate ctx-info) free) ) ) ) ) ;module message-digest-primitive