;;;; message-digest-type.scm ;;;; Kon Lovett, Jan '06 (message-digest.scm) ;;;; Kon Lovett, May '10 (message-digest.scm) ;;;; Kon Lovett, Apr '12 ;;;; Kon Lovett, Aug '17 ;; Issues ;; ;; - Uses 'context-info' to determine whether active context is "own" allocation or ;; callers. (module message-digest-type (;export ; MD API message-digest-default-result-type ;DEPRECATED message-digest-result-form message-digest? check-message-digest error-message-digest message-digest-algorithm message-digest-context initialize-message-digest finalize-message-digest setup-message-digest-buffer!) (import scheme) (import chicken (only lolevel allocate free number-of-bytes) (only srfi-4 blob->u8vector/shared)) (require-library lolevel srfi-4) (import (only blob-hexadecimal blob->hex) (only string-hexadecimal string->hex) (only type-checks define-check+error-type) (only type-errors error-argument-type)) (require-library blob-hexadecimal string-hexadecimal type-checks type-errors) (require-extension miscmacros message-digest-primitive) ;;; Support (define-constant MINIMUM-BUFFER-SIZE 8) #; ;CHICKEN 4.8.0.5 has an issue here (define-constant DEFAULT-RESULT-TYPE 'hex-string) (define (error-result-form loc obj) (error-argument-type loc obj "symbol in {string hex blob u8vector}" 'result-form) ) ;perform any conversion necessary for final result representation ;assumes blob 'res' may not be of result size #; (define (get-result-form loc res rt len) (case rt ((blob) (if (fx= len (blob-size res)) res (string->blob (substring (blob->string res) 0 len)) ) ) ((byte-string string) (let ((str (blob->string res))) (if (fx= len (string-length str)) str (substring str 0 len) ) ) ) ((hex-string hex hexstring) (blob->hex res 0 len) ) ((u8vector) (let ((vec (blob->u8vector/shared res))) (if (fx= len (u8vector-length vec)) vec (subu8vector vec 0 len) ) ) ) (else (error-result-form loc rt) ) ) ) ;perform any conversion necessary for final result representation ;assumes blob 'res' is of result size (define (get-result-form loc res rt) (case (canonical-result-name rt) ((blob) res ) ((byte-string) (blob->string res) ) ((hex-string) (blob->hex res) ) ((u8vector) (blob->u8vector/shared res) ) (else (error-result-form loc rt) ) ) ) (define (canonical-result-name x) (case x ((blob) 'blob ) ((byte-string string) 'byte-string ) ((hex-string hex hexstring) 'hex-string ) ((u8vector) 'u8vector ) (else #f ) ) ) ;;; Message Digest API ;; (define-parameter message-digest-result-form #;DEFAULT-RESULT-TYPE 'hex-string (lambda (x) (or (if x (canonical-result-name x) #;DEFAULT-RESULT-TYPE 'hex-string) (begin (warning 'message-digest-result-form "invalid result-form" x) (message-digest-result-form) ) ) ) ) ;DEPRECATED (define message-digest-default-result-type message-digest-result-form) ;; (define-record-type message-digest (*make-message-digest mdp ctx buf) message-digest? (mdp message-digest-algorithm) (ctx message-digest-context) (buf message-digest-buffer message-digest-buffer-set!) ) (define-check+error-type message-digest) ;; (define (get-message-digest-primitive-context mdp) (let ((ctx-info (message-digest-primitive-context-info mdp))) (if (procedure? ctx-info) (ctx-info) (set-finalizer! (allocate ctx-info) free) ) ) ) ;; (define (initialize-message-digest mdp) (let ((ctx (get-message-digest-primitive-context (check-message-digest-primitive 'initialize-message-digest mdp)))) ((message-digest-primitive-init mdp) ctx) (*make-message-digest mdp ctx #f) ) ) ;; (define (finalize-message-digest md #!optional (result-type (message-digest-result-form))) (let* ((mdp (message-digest-algorithm (check-message-digest 'finalize-message-digest md))) (res (make-blob (message-digest-primitive-digest-length mdp))) ) ((message-digest-primitive-final mdp) (message-digest-context md) res) ;side-effects res (get-result-form 'finalize-message-digest res result-type) ) ) ;; (define (setup-message-digest-buffer! md sz) (let ((buf (message-digest-buffer md)) (sz (fxmax sz MINIMUM-BUFFER-SIZE)) ) ;enough space? then reuse, otherwise new buffer (if (and buf (fx<= sz (number-of-bytes buf))) buf (new-message-digest-buffer! md sz) ) ) ) (define (new-message-digest-buffer! md sz) (let ((buf (make-blob sz))) (message-digest-buffer-set! md buf) buf ) ) ) ;module message-digest-type