From 25afd7a2e7b16a304c6bb1de4706458bb61484e8 Mon Sep 17 00:00:00 2001
From: Chris Hanson <org/chris-hanson/cph>
Date: Tue, 17 Jun 1997 04:58:06 +0000
Subject: [PATCH] Add new primitives to simplify writing code to perform MD5
 checksum on arbitrary-length streams.

---
 v7/src/microcode/prmd5.c | 63 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 61 insertions(+), 2 deletions(-)

diff --git a/v7/src/microcode/prmd5.c b/v7/src/microcode/prmd5.c
index f5c9148c3..59d9186a2 100644
--- a/v7/src/microcode/prmd5.c
+++ b/v7/src/microcode/prmd5.c
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: prmd5.c,v 1.2 1997/06/09 21:17:11 cph Exp $
+$Id: prmd5.c,v 1.3 1997/06/17 04:58:06 cph Exp $
 
 Copyright (c) 1997 Massachusetts Institute of Technology
 
@@ -37,7 +37,7 @@ MIT in each case. */
 #include "scheme.h"
 #include "prims.h"
 #include <md5.h>
-
+
 DEFINE_PRIMITIVE ("MD5", Prim_md5, 1, 1,
   "(STRING)\n\
 Generate an MD5 digest of string.\n\
@@ -60,3 +60,62 @@ The digest is returned as a 16-byte string.")
     PRIMITIVE_RETURN (result);
   }
 }
+
+DEFINE_PRIMITIVE ("MD5-INIT", Prim_md5_init, 0, 0,
+  "()\n\
+Create and return an MD5 digest context.")
+{
+  PRIMITIVE_HEADER (0);
+  {
+    SCHEME_OBJECT context = (allocate_string (sizeof (MD5_CTX)));
+    MD5Init ((MD5_CTX *) (STRING_LOC (context, 0)));
+    PRIMITIVE_RETURN (context);
+  }
+}
+
+static MD5_CTX *
+DEFUN (md5_context_arg, (arg), int arg)
+{
+  CHECK_ARG (arg, STRING_P);
+  if ((STRING_LENGTH (ARG_REF (arg))) != (sizeof (MD5_CTX)))
+    error_bad_range_arg (arg);
+  return ((MD5_CTX *) (STRING_LOC ((ARG_REF (arg)), 0)));
+}
+
+DEFINE_PRIMITIVE ("MD5-UPDATE", Prim_md5_update, 4, 4,
+  "(CONTEXT STRING START END)\n\
+Update CONTEXT with the contents of the substring (STRING,START,END).")
+{
+  PRIMITIVE_HEADER (4);
+  CHECK_ARG (2, STRING_P);
+  {
+    SCHEME_OBJECT string = (ARG_REF (2));
+    unsigned long l = (STRING_LENGTH (string));
+    unsigned long start = (arg_ulong_index_integer (3, l));
+    unsigned long end = (arg_integer_in_range (4, start, (l + 1)));
+    MD5Update ((md5_context_arg (1)),
+	       (STRING_LOC (string, start)),
+	       (end - start));
+    PRIMITIVE_RETURN (UNSPECIFIC);
+  }
+}
+
+DEFINE_PRIMITIVE ("MD5-FINAL", Prim_md5_final, 1, 1,
+  "(CONTEXT)\n\
+Finalize CONTEXT and return the digest as a 16-byte string.")
+{
+  PRIMITIVE_HEADER (1);
+  {
+    MD5_CTX * context = (md5_context_arg (1));
+    MD5Final (context);
+    {
+      SCHEME_OBJECT result = (allocate_string (16));
+      unsigned char * scan_result = (STRING_LOC (result, 0));
+      unsigned char * scan_digest = (context -> digest);
+      unsigned char * end_digest = (scan_digest + 16);
+      while (scan_digest < end_digest)
+	(*scan_result++) = (*scan_digest++);
+      PRIMITIVE_RETURN (result);
+    }
+  }
+}
-- 
2.25.1