| 1 | # md4c.tcl - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sourceforge.net> |
|---|
| 2 | # |
|---|
| 3 | # This provides a C implementation of MD4 using the sample code from RFC1320 |
|---|
| 4 | # and wrapping this up in a Tcl package. |
|---|
| 5 | # |
|---|
| 6 | # The tcl interface code is based upon the md5c code from critcl by JCW. |
|---|
| 7 | # |
|---|
| 8 | # INSTALLATION |
|---|
| 9 | # ------------ |
|---|
| 10 | # This package uses critcl (http://wiki.tcl.tk/critcl). To build do: |
|---|
| 11 | # critcl -libdir <your-tcl-lib-dir> -pkg md4c md4c |
|---|
| 12 | # |
|---|
| 13 | # $Id: md4c.tcl,v 1.4 2004/01/15 06:36:13 andreas_kupries Exp $ |
|---|
| 14 | |
|---|
| 15 | package require critcl |
|---|
| 16 | package provide md4c 1.0.0 |
|---|
| 17 | |
|---|
| 18 | critcl::cheaders md4.h |
|---|
| 19 | critcl::csources md4.c |
|---|
| 20 | |
|---|
| 21 | namespace eval ::md4 { |
|---|
| 22 | |
|---|
| 23 | critcl::ccode { |
|---|
| 24 | #include "md4.h" |
|---|
| 25 | |
|---|
| 26 | /* |
|---|
| 27 | * define a Tcl object type for the MD4 state |
|---|
| 28 | */ |
|---|
| 29 | static Tcl_ObjType md4_type; |
|---|
| 30 | |
|---|
| 31 | static void md4_free_rep(Tcl_Obj *obj) |
|---|
| 32 | { |
|---|
| 33 | MD4_CTX *ctx = (MD4_CTX *)obj->internalRep.otherValuePtr; |
|---|
| 34 | Tcl_Free((char *)ctx); |
|---|
| 35 | } |
|---|
| 36 | |
|---|
| 37 | static void md4_dup_rep(Tcl_Obj *obj, Tcl_Obj *dup) |
|---|
| 38 | { |
|---|
| 39 | MD4_CTX *ctx = (MD4_CTX *)obj->internalRep.otherValuePtr; |
|---|
| 40 | dup->internalRep.otherValuePtr = (MD4_CTX *)Tcl_Alloc(sizeof(MD4_CTX)); |
|---|
| 41 | memcpy(dup->internalRep.otherValuePtr, ctx, sizeof(MD4_CTX)); |
|---|
| 42 | dup->typePtr = &md4_type; |
|---|
| 43 | } |
|---|
| 44 | |
|---|
| 45 | static void md4_string_rep(Tcl_Obj* obj) |
|---|
| 46 | { |
|---|
| 47 | unsigned char buf[16]; |
|---|
| 48 | Tcl_Obj* temp; |
|---|
| 49 | char* str; |
|---|
| 50 | MD4_CTX *dup = (MD4_CTX *)obj->internalRep.otherValuePtr; |
|---|
| 51 | |
|---|
| 52 | MD4Final(buf, dup); |
|---|
| 53 | |
|---|
| 54 | /* convert via a byte array to properly handle null bytes */ |
|---|
| 55 | temp = Tcl_NewByteArrayObj(buf, sizeof buf); |
|---|
| 56 | Tcl_IncrRefCount(temp); |
|---|
| 57 | |
|---|
| 58 | str = Tcl_GetStringFromObj(temp, &obj->length); |
|---|
| 59 | obj->bytes = Tcl_Alloc(obj->length + 1); |
|---|
| 60 | memcpy(obj->bytes, str, obj->length + 1); |
|---|
| 61 | |
|---|
| 62 | Tcl_DecrRefCount(temp); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | static int md4_from_any(Tcl_Interp* interp, Tcl_Obj* obj) |
|---|
| 66 | { |
|---|
| 67 | /* assert(0); */ |
|---|
| 68 | return TCL_ERROR; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | static Tcl_ObjType md4_type = { |
|---|
| 72 | "md4c", md4_free_rep, md4_dup_rep, md4_string_rep, md4_from_any |
|---|
| 73 | }; |
|---|
| 74 | |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | critcl::ccommand md4c {dummy interp objc objv} { |
|---|
| 78 | MD4_CTX *ctx; |
|---|
| 79 | unsigned char* data; |
|---|
| 80 | int size; |
|---|
| 81 | Tcl_Obj* obj; |
|---|
| 82 | |
|---|
| 83 | /* Tcl_RegisterObjType(&md4_type); */ |
|---|
| 84 | |
|---|
| 85 | if (objc < 2 || objc > 3) { |
|---|
| 86 | Tcl_WrongNumArgs(interp, 1, objv, "data ?context?"); |
|---|
| 87 | return TCL_ERROR; |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | if (objc == 3) { |
|---|
| 91 | if (objv[2]->typePtr != &md4_type |
|---|
| 92 | && md4_from_any(interp, objv[2]) != TCL_OK) |
|---|
| 93 | return TCL_ERROR; |
|---|
| 94 | obj = objv[2]; |
|---|
| 95 | if (Tcl_IsShared(obj)) |
|---|
| 96 | obj = Tcl_DuplicateObj(obj); |
|---|
| 97 | } else { |
|---|
| 98 | obj = Tcl_NewObj(); |
|---|
| 99 | ctx = (MD4_CTX *)Tcl_Alloc(sizeof(MD4_CTX)); |
|---|
| 100 | MD4Init(ctx); |
|---|
| 101 | |
|---|
| 102 | if (obj->typePtr != NULL && obj->typePtr->freeIntRepProc != NULL) |
|---|
| 103 | obj->typePtr->freeIntRepProc(obj); |
|---|
| 104 | |
|---|
| 105 | obj->internalRep.otherValuePtr = ctx; |
|---|
| 106 | obj->typePtr = &md4_type; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | Tcl_SetObjResult(interp, obj); |
|---|
| 110 | Tcl_IncrRefCount(obj); //!! huh? |
|---|
| 111 | |
|---|
| 112 | Tcl_InvalidateStringRep(obj); |
|---|
| 113 | ctx = (MD4_CTX *)obj->internalRep.otherValuePtr; |
|---|
| 114 | |
|---|
| 115 | data = Tcl_GetByteArrayFromObj(objv[1], &size); |
|---|
| 116 | MD4Update(ctx, data, size); |
|---|
| 117 | |
|---|
| 118 | return TCL_OK; |
|---|
| 119 | } |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | # Local variables: |
|---|
| 123 | # mode: tcl |
|---|
| 124 | # indent-tabs-mode: nil |
|---|
| 125 | # End: |
|---|