--- /dev/null
+;;; blah
+
+(cl-interpol:enable-interpol-syntax)
+
+(loop
+ for (mech hashsz hash) in '((sha1ppss 160 sha)
+ (sha256ppss 256 sha256)
+ (sha384ppss 384 sha384)
+ (sha512ppss 512 sha512))
+ do (setf (get mech 'hashsz) hashsz)
+ (setf (get mech 'hash) hash))
+
+(defun skip-blank-lines (stream)
+ (loop
+ (let ((ch (read-char stream nil nil)))
+ (case ch
+ (nil (return nil))
+ (#\newline nil)
+ (t (unread-char ch stream)
+ (return t))))))
+
+(defun parse-stanza (stream)
+ (flet ((parse-header ()
+ (let ((head (read-line stream nil nil)))
+ (and head
+ (cl-ppcre:register-groups-bind
+ (mech (#'parse-integer nbits))
+ (#?/^(\w+),\s+mod(?:size|len)\s+(\d+)/ ;|)
+ head :sharedp t)
+ (values (intern (string-upcase mech)) nbits)))))
+ (check-banner (banner)
+ (let ((line (read-line stream)))
+ (unless (string= line banner)
+ (error "missing banner line `~A' (found `~A')" banner line))))
+ (parse-hexgorp (bits)
+ (with-output-to-string (gorp)
+ (loop
+ (unless (plusp bits)
+ (return))
+ (let ((line (read-line stream)))
+ (when (string= line "")
+ (return))
+ (unless (cl-ppcre:scan #?/^[0-9A-F-a-f\s]+$/ line)
+ (error "bad hex string `~A'" line))
+ (setf line (cl-ppcre:regex-replace-all #?/\s+/ line ""))
+ (decf bits (* 4 (length line)))
+ (princ line gorp))))))
+ (skip-blank-lines stream)
+ (multiple-value-bind (mech nbits) (parse-header)
+ (when mech
+ (let (hash out)
+ (check-banner "Input data is")
+ (setf hash (parse-hexgorp (get mech 'hashsz)))
+ (check-banner "Padded output is")
+ (setf out (parse-hexgorp nbits))
+ (format t "~
+~( ~A
+ 0x~A
+ \"~A\" 0 \"\"
+ ~A-mgf ~:*~A ~A~)~%"
+ nbits
+ out
+ hash
+ (get mech 'hash)
+ (get mech 'hashsz))
+ t)))))
+
+(with-open-file (str "/tmp/mdw/psstests")
+ (parse-stanza str))