Browse Source

core/crypto/md4: Remove, badly broken

Yawning Angel 1 year ago
parent
commit
235fec23af

+ 0 - 1
core/crypto/README.md

@@ -11,7 +11,6 @@ Please see the chart below for the options.
 | [BLAKE2B](https://datatracker.ietf.org/doc/html/rfc7693)                                                     | ✔️ |
 | [BLAKE2S](https://datatracker.ietf.org/doc/html/rfc7693)                                                     | ✔️ |
 | [Keccak](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf)                                           | ✔️ |
-| [MD4](https://datatracker.ietf.org/doc/html/rfc1320)                                                         | ✔️ |
 | [MD5](https://datatracker.ietf.org/doc/html/rfc1321)                                                         | ✔️ |
 | [RIPEMD](https://homes.esat.kuleuven.be/~bosselae/ripemd160.html)                                            | ✔️ |
 | [SHA-1](https://datatracker.ietf.org/doc/html/rfc3174)                                                       | ✔️ |

+ 0 - 263
core/crypto/md4/md4.odin

@@ -1,263 +0,0 @@
-package md4
-
-/*
-    Copyright 2021 zhibog
-    Made available under the BSD-3 license.
-
-    List of contributors:
-        zhibog, dotbmp:  Initial implementation.
-        Jeroen van Rijn: Context design to be able to change from Odin implementation to bindings.
-
-    Implementation of the MD4 hashing algorithm, as defined in RFC 1320 <https://datatracker.ietf.org/doc/html/rfc1320>
-*/
-
-import "core:mem"
-import "core:os"
-import "core:io"
-
-import "../util"
-
-/*
-    High level API
-*/
-
-DIGEST_SIZE :: 16
-
-// hash_string will hash the given input and return the
-// computed hash
-hash_string :: proc(data: string) -> [DIGEST_SIZE]byte {
-    return hash_bytes(transmute([]byte)(data))
-}
-
-// hash_bytes will hash the given input and return the
-// computed hash
-hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
-    hash: [DIGEST_SIZE]byte
-    ctx: Md4_Context
-    init(&ctx)
-    update(&ctx, data)
-    final(&ctx, hash[:])
-    return hash
-}
-
-// hash_string_to_buffer will hash the given input and assign the
-// computed hash to the second parameter.
-// It requires that the destination buffer is at least as big as the digest size
-hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash)
-}
-
-// hash_bytes_to_buffer will hash the given input and write the
-// computed hash into the second parameter.
-// It requires that the destination buffer is at least as big as the digest size
-hash_bytes_to_buffer :: proc(data, hash: []byte) {
-    assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
-    ctx: Md4_Context
-    init(&ctx)
-    update(&ctx, data)
-    final(&ctx, hash)
-}
-
-// hash_stream will read the stream in chunks and compute a
-// hash from its contents
-hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
-    hash: [DIGEST_SIZE]byte
-    ctx: Md4_Context
-    init(&ctx)
-    buf := make([]byte, 512)
-    defer delete(buf)
-    read := 1
-    for read > 0 {
-        read, _ = io.read(s, buf)
-        if read > 0 {
-            update(&ctx, buf[:read])
-        } 
-    }
-    final(&ctx, hash[:])
-    return hash, true
-}
-
-// hash_file will read the file provided by the given handle
-// and compute a hash
-hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) {
-    if !load_at_once {
-        return hash_stream(os.stream_from_handle(hd))
-    } else {
-        if buf, ok := os.read_entire_file(hd); ok {
-            return hash_bytes(buf[:]), ok
-        }
-    }
-    return [DIGEST_SIZE]byte{}, false
-}
-
-hash :: proc {
-    hash_stream,
-    hash_file,
-    hash_bytes,
-    hash_string,
-    hash_bytes_to_buffer,
-    hash_string_to_buffer,
-}
-
-/*
-    Low level API
-*/
-
-init :: proc(ctx: ^Md4_Context) {
-    ctx.state[0] = 0x67452301
-    ctx.state[1] = 0xefcdab89
-    ctx.state[2] = 0x98badcfe
-    ctx.state[3] = 0x10325476
-}
-
-update :: proc(ctx: ^Md4_Context, data: []byte) {
-    for i := 0; i < len(data); i += 1 {
-        ctx.data[ctx.datalen] = data[i]
-        ctx.datalen += 1
-        if(ctx.datalen == BLOCK_SIZE) {
-            transform(ctx, ctx.data[:])
-            ctx.bitlen += 512
-            ctx.datalen = 0
-        }
-    }
-}
-
-final :: proc(ctx: ^Md4_Context, hash: []byte) {
-    i := ctx.datalen
-    if ctx.datalen < 56 {
-        ctx.data[i] = 0x80
-        i += 1
-        for i < 56 {
-            ctx.data[i] = 0x00
-            i += 1
-        }
-    } else if ctx.datalen >= 56 {
-        ctx.data[i] = 0x80
-        i += 1
-        for i < BLOCK_SIZE {
-            ctx.data[i] = 0x00
-            i += 1
-        }
-        transform(ctx, ctx.data[:])
-        mem.set(&ctx.data, 0, 56)
-    }
-
-    ctx.bitlen  += u64(ctx.datalen * 8)
-    ctx.data[56] = byte(ctx.bitlen)
-    ctx.data[57] = byte(ctx.bitlen >> 8)
-    ctx.data[58] = byte(ctx.bitlen >> 16)
-    ctx.data[59] = byte(ctx.bitlen >> 24)
-    ctx.data[60] = byte(ctx.bitlen >> 32)
-    ctx.data[61] = byte(ctx.bitlen >> 40)
-    ctx.data[62] = byte(ctx.bitlen >> 48)
-    ctx.data[63] = byte(ctx.bitlen >> 56)
-    transform(ctx, ctx.data[:])
-
-    for i = 0; i < 4; i += 1 {
-        hash[i]      = byte(ctx.state[0] >> (i * 8)) & 0x000000ff
-        hash[i + 4]  = byte(ctx.state[1] >> (i * 8)) & 0x000000ff
-        hash[i + 8]  = byte(ctx.state[2] >> (i * 8)) & 0x000000ff
-        hash[i + 12] = byte(ctx.state[3] >> (i * 8)) & 0x000000ff
-    }
-}
-
-/*
-    MD4 implementation
-*/
-
-BLOCK_SIZE  :: 64
-
-Md4_Context :: struct {
-    data:    [64]byte,
-    state:   [4]u32,
-    bitlen:  u64,
-    datalen: u32,
-}
-
-/*
-    @note(zh): F, G and H, as mentioned in the RFC, have been inlined into FF, GG 
-    and HH respectively, instead of declaring them separately.
-*/
-
-FF :: #force_inline proc "contextless"(a, b, c, d, x: u32, s : int) -> u32 {
-    return util.ROTL32(a + ((b & c) | (~b & d)) + x, s)
-}
-
-GG :: #force_inline proc "contextless"(a, b, c, d, x: u32, s : int) -> u32 {
-    return util.ROTL32(a + ((b & c) | (b & d) | (c & d)) + x + 0x5a827999, s)
-}
-
-HH :: #force_inline proc "contextless"(a, b, c, d, x: u32, s : int) -> u32 {
-    return util.ROTL32(a + (b ~ c ~ d) + x + 0x6ed9eba1, s)
-}
-
-transform :: proc(ctx: ^Md4_Context, data: []byte) {
-    a, b, c, d, i, j: u32
-    m: [DIGEST_SIZE]u32
-
-    for i, j = 0, 0; i < DIGEST_SIZE; i += 1 {
-        m[i] = u32(data[j]) | (u32(data[j + 1]) << 8) | (u32(data[j + 2]) << 16) | (u32(data[j + 3]) << 24)
-        j += 4
-    }
-
-    a = ctx.state[0]
-    b = ctx.state[1]
-    c = ctx.state[2]
-    d = ctx.state[3]
-
-    a = FF(a, b, c, d, m[0],  3)
-    d = FF(d, a, b, c, m[1],  7)
-    c = FF(c, d, a, b, m[2],  11)
-    b = FF(b, c, d, a, m[3],  19)
-    a = FF(a, b, c, d, m[4],  3)
-    d = FF(d, a, b, c, m[5],  7)
-    c = FF(c, d, a, b, m[6],  11)
-    b = FF(b, c, d, a, m[7],  19)
-    a = FF(a, b, c, d, m[8],  3)
-    d = FF(d, a, b, c, m[9],  7)
-    c = FF(c, d, a, b, m[10], 11)
-    b = FF(b, c, d, a, m[11], 19)
-    a = FF(a, b, c, d, m[12], 3)
-    d = FF(d, a, b, c, m[13], 7)
-    c = FF(c, d, a, b, m[14], 11)
-    b = FF(b, c, d, a, m[15], 19)
-
-    a = GG(a, b, c, d, m[0],  3)
-    d = GG(d, a, b, c, m[4],  5)
-    c = GG(c, d, a, b, m[8],  9)
-    b = GG(b, c, d, a, m[12], 13)
-    a = GG(a, b, c, d, m[1],  3)
-    d = GG(d, a, b, c, m[5],  5)
-    c = GG(c, d, a, b, m[9],  9)
-    b = GG(b, c, d, a, m[13], 13)
-    a = GG(a, b, c, d, m[2],  3)
-    d = GG(d, a, b, c, m[6],  5)
-    c = GG(c, d, a, b, m[10], 9)
-    b = GG(b, c, d, a, m[14], 13)
-    a = GG(a, b, c, d, m[3],  3)
-    d = GG(d, a, b, c, m[7],  5)
-    c = GG(c, d, a, b, m[11], 9)
-    b = GG(b, c, d, a, m[15], 13)
-
-    a = HH(a, b, c, d, m[0],  3)
-    d = HH(d, a, b, c, m[8],  9)
-    c = HH(c, d, a, b, m[4],  11)
-    b = HH(b, c, d, a, m[12], 15)
-    a = HH(a, b, c, d, m[2],  3)
-    d = HH(d, a, b, c, m[10], 9)
-    c = HH(c, d, a, b, m[6],  11)
-    b = HH(b, c, d, a, m[14], 15)
-    a = HH(a, b, c, d, m[1],  3)
-    d = HH(d, a, b, c, m[9],  9)
-    c = HH(c, d, a, b, m[5],  11)
-    b = HH(b, c, d, a, m[13], 15)
-    a = HH(a, b, c, d, m[3],  3)
-    d = HH(d, a, b, c, m[11], 9)
-    c = HH(c, d, a, b, m[7],  11)
-    b = HH(b, c, d, a, m[15], 15)
-
-    ctx.state[0] += a
-    ctx.state[1] += b
-    ctx.state[2] += c
-    ctx.state[3] += d
-}

+ 0 - 2
examples/all/all_main.odin

@@ -28,7 +28,6 @@ import blake2s          "core:crypto/blake2s"
 import chacha20         "core:crypto/chacha20"
 import chacha20poly1305 "core:crypto/chacha20poly1305"
 import keccak           "core:crypto/keccak"
-import md4              "core:crypto/md4"
 import md5              "core:crypto/md5"
 import poly1305         "core:crypto/poly1305"
 import ripemd           "core:crypto/ripemd"
@@ -149,7 +148,6 @@ _ :: blake2s
 _ :: chacha20
 _ :: chacha20poly1305
 _ :: keccak
-_ :: md4
 _ :: md5
 _ :: poly1305
 _ :: ripemd

+ 0 - 2
examples/all/all_vendor.odin

@@ -3,7 +3,6 @@ package all
 import botan_bindings "vendor:botan/bindings"
 import botan_blake2b  "vendor:botan/blake2b"
 import keccak         "vendor:botan/keccak"
-import md4            "vendor:botan/md4"
 import md5            "vendor:botan/md5"
 import ripemd         "vendor:botan/ripemd"
 import sha1           "vendor:botan/sha1"
@@ -48,7 +47,6 @@ import fontstash "vendor:fontstash"
 _ :: botan_bindings
 _ :: botan_blake2b
 _ :: keccak
-_ :: md4
 _ :: md5
 _ :: ripemd
 _ :: sha1

+ 0 - 21
tests/core/crypto/test_core_crypto.odin

@@ -16,7 +16,6 @@ import "core:testing"
 import "core:fmt"
 import "core:strings"
 
-import "core:crypto/md4"
 import "core:crypto/md5"
 import "core:crypto/sha1"
 import "core:crypto/sha2"
@@ -57,7 +56,6 @@ when ODIN_TEST {
 
 main :: proc() {
 	t := testing.T{}
-	test_md4(&t)
 	test_md5(&t)
 	test_sha1(&t)
 	test_sha224(&t)
@@ -123,25 +121,6 @@ hex_string :: proc(bytes: []byte, allocator := context.temp_allocator) -> string
 	return string(buf)
 }
 
-@(test)
-test_md4 :: proc(t: ^testing.T) {
-	// Official test vectors from https://datatracker.ietf.org/doc/html/rfc1320
-	test_vectors := [?]TestHash {
-		TestHash{"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
-		TestHash{"bde52cb31de33e46245e05fbdbd6fb24", "a"},
-		TestHash{"a448017aaf21d8525fc10ae87aa6729d", "abc"},
-		TestHash{"d9130a8164549fe818874806e1c7014b", "message digest"},
-		TestHash{"d79e1c308aa5bbcdeea8ed63df412da9", "abcdefghijklmnopqrstuvwxyz"},
-		TestHash{"043f8582f241db351ce627e153e7f0e4", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
-		TestHash{"e33b4ddc9c38f2199c3e7b164fcc0536", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
-	}
-	for v, _ in test_vectors {
-		computed     := md4.hash(v.str)
-		computed_str := hex_string(computed[:])
-		expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
-	}
-}
-
 @(test)
 test_md5 :: proc(t: ^testing.T) {
 	// Official test vectors from https://datatracker.ietf.org/doc/html/rfc1321

+ 0 - 21
tests/vendor/botan/test_vendor_botan.odin

@@ -17,7 +17,6 @@ import "core:fmt"
 import "core:os"
 import "core:strings"
 
-import "vendor:botan/md4"
 import "vendor:botan/md5"
 import "vendor:botan/sha1"
 import "vendor:botan/sha2"
@@ -58,7 +57,6 @@ when ODIN_TEST {
 
 main :: proc() {
     t := testing.T{}
-    test_md4(&t)
     test_md5(&t)
     test_sha1(&t)
     test_sha224(&t)
@@ -106,25 +104,6 @@ hex_string :: proc(bytes: []byte, allocator := context.temp_allocator) -> string
     return string(buf)
 }
 
-@(test)
-test_md4 :: proc(t: ^testing.T) {
-    // Official test vectors from https://datatracker.ietf.org/doc/html/rfc1320
-    test_vectors := [?]TestHash {
-        TestHash{"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
-        TestHash{"bde52cb31de33e46245e05fbdbd6fb24", "a"},
-        TestHash{"a448017aaf21d8525fc10ae87aa6729d", "abc"},
-        TestHash{"d9130a8164549fe818874806e1c7014b", "message digest"},
-        TestHash{"d79e1c308aa5bbcdeea8ed63df412da9", "abcdefghijklmnopqrstuvwxyz"},
-        TestHash{"043f8582f241db351ce627e153e7f0e4", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
-        TestHash{"e33b4ddc9c38f2199c3e7b164fcc0536", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
-    }
-    for v, _ in test_vectors {
-        computed     := md4.hash(v.str)
-        computed_str := hex_string(computed[:])
-        expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
-    }
-}
-
 @(test)
 test_md5 :: proc(t: ^testing.T) {
     // Official test vectors from https://datatracker.ietf.org/doc/html/rfc1321

+ 0 - 1
vendor/botan/README.md

@@ -10,7 +10,6 @@ Wrappers for hashing algorithms have been added to match the API within the Odin
 |:-------------------------------------------------------------------------------------------------------------|:-----------------|
 | [BLAKE2B](https://datatracker.ietf.org/doc/html/rfc7693)                                                     | &#10004;&#65039; |
 | [Keccak](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf)                                           | &#10004;&#65039; |
-| [MD4](https://datatracker.ietf.org/doc/html/rfc1320)                                                         | &#10004;&#65039; |
 | [MD5](https://datatracker.ietf.org/doc/html/rfc1321)                                                         | &#10004;&#65039; |
 | [RIPEMD-160](https://homes.esat.kuleuven.be/~bosselae/ripemd160.html)                                        | &#10004;&#65039; |
 | [SHA-1](https://datatracker.ietf.org/doc/html/rfc3174)                                                       | &#10004;&#65039; |

+ 0 - 1
vendor/botan/bindings/botan.odin

@@ -77,7 +77,6 @@ HASH_KECCAK_512     :: "Keccak-1600"
 HASH_RIPEMD_160     :: "RIPEMD-160"
 HASH_WHIRLPOOL      :: "Whirlpool"
 HASH_BLAKE2B        :: "BLAKE2b"
-HASH_MD4            :: "MD4"
 HASH_MD5            :: "MD5"
 HASH_TIGER_128      :: "Tiger(16,3)"
 HASH_TIGER_160      :: "Tiger(20,3)"

+ 0 - 121
vendor/botan/md4/md4.odin

@@ -1,121 +0,0 @@
-package vendor_md4
-
-/*
-    Copyright 2021 zhibog
-    Made available under the BSD-3 license.
-
-    List of contributors:
-        zhibog:  Initial implementation.
-
-    Interface for the MD4 hashing algorithm.
-    The hash will be computed via bindings to the Botan crypto library
-*/
-
-import "core:os"
-import "core:io"
-
-import botan "../bindings"
-
-/*
-    High level API
-*/
-
-DIGEST_SIZE :: 16
-
-// hash_string will hash the given input and return the
-// computed hash
-hash_string :: proc "contextless" (data: string) -> [DIGEST_SIZE]byte {
-    return hash_bytes(transmute([]byte)(data))
-}
-
-// hash_bytes will hash the given input and return the
-// computed hash
-hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
-    hash: [DIGEST_SIZE]byte
-    ctx: botan.hash_t
-    botan.hash_init(&ctx, botan.HASH_MD4, 0)
-    botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
-    botan.hash_final(ctx, &hash[0])
-    botan.hash_destroy(ctx)
-    return hash
-}
-
-// hash_string_to_buffer will hash the given input and assign the
-// computed hash to the second parameter.
-// It requires that the destination buffer is at least as big as the digest size
-hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash)
-}
-
-// hash_bytes_to_buffer will hash the given input and write the
-// computed hash into the second parameter.
-// It requires that the destination buffer is at least as big as the digest size
-hash_bytes_to_buffer :: proc(data, hash: []byte) {
-    assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
-    ctx: botan.hash_t
-    botan.hash_init(&ctx, botan.HASH_MD4, 0)
-    botan.hash_update(ctx, len(data) == 0 ? nil : &data[0], uint(len(data)))
-    botan.hash_final(ctx, &hash[0])
-    botan.hash_destroy(ctx)
-}
-
-// hash_stream will read the stream in chunks and compute a
-// hash from its contents
-hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
-    hash: [DIGEST_SIZE]byte
-    ctx: botan.hash_t
-    botan.hash_init(&ctx, botan.HASH_MD4, 0)
-    buf := make([]byte, 512)
-    defer delete(buf)
-    i := 1
-    for i > 0 {
-        i, _ = io.read(s, buf)
-        if i > 0 {
-            botan.hash_update(ctx, len(buf) == 0 ? nil : &buf[0], uint(i))
-        } 
-    }
-    botan.hash_final(ctx, &hash[0])
-    botan.hash_destroy(ctx)
-    return hash, true 
-}
-
-// hash_file will read the file provided by the given handle
-// and compute a hash
-hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([DIGEST_SIZE]byte, bool) {
-    if !load_at_once {
-        return hash_stream(os.stream_from_handle(hd))
-    } else {
-        if buf, ok := os.read_entire_file(hd); ok {
-            return hash_bytes(buf[:]), ok
-        }
-    }
-    return [DIGEST_SIZE]byte{}, false
-}
-
-hash :: proc {
-    hash_stream,
-    hash_file,
-    hash_bytes,
-    hash_string,
-    hash_bytes_to_buffer,
-    hash_string_to_buffer,
-}
-
-/*
-    Low level API
-*/
-
-Md4_Context :: botan.hash_t
-
-init :: proc "contextless" (ctx: ^botan.hash_t) {
-    botan.hash_init(ctx, botan.HASH_MD4, 0)
-}
-
-update :: proc "contextless" (ctx: ^botan.hash_t, data: []byte) {
-    botan.hash_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
-}
-
-final :: proc "contextless" (ctx: ^botan.hash_t, hash: []byte) {
-    botan.hash_final(ctx^, &hash[0])
-    botan.hash_destroy(ctx^)
-}