Removed context switching system from the crypto library to simplify the code

This commit is contained in:
zhibog
2021-11-09 16:50:13 +01:00
parent eb96f9677e
commit c24454ae70
32 changed files with 3124 additions and 7327 deletions
+128 -285
View File
@@ -6,7 +6,6 @@ package sha3
List of contributors:
zhibog, dotbmp: Initial implementation.
Jeroen van Rijn: Context design to be able to change from Odin implementation to bindings.
Interface for the SHA3 hashing algorithm. The SHAKE functionality can be found in package shake.
If you wish to compute a Keccak hash, you can use the keccak package, it will use the original padding.
@@ -15,58 +14,8 @@ package sha3
import "core:os"
import "core:io"
import "../botan"
import "../_ctx"
import "../_sha3"
/*
Context initialization and switching between the Odin implementation and the bindings
*/
USE_BOTAN_LIB :: bool(#config(USE_BOTAN_LIB, false))
@(private)
_init_vtable :: #force_inline proc() -> ^_ctx.Hash_Context {
ctx := _ctx._init_vtable()
when USE_BOTAN_LIB {
use_botan()
} else {
_assign_hash_vtable(ctx)
}
return ctx
}
@(private)
_assign_hash_vtable :: #force_inline proc(ctx: ^_ctx.Hash_Context) {
ctx.hash_bytes_28 = hash_bytes_odin_28
ctx.hash_file_28 = hash_file_odin_28
ctx.hash_stream_28 = hash_stream_odin_28
ctx.hash_bytes_32 = hash_bytes_odin_32
ctx.hash_file_32 = hash_file_odin_32
ctx.hash_stream_32 = hash_stream_odin_32
ctx.hash_bytes_48 = hash_bytes_odin_48
ctx.hash_file_48 = hash_file_odin_48
ctx.hash_stream_48 = hash_stream_odin_48
ctx.hash_bytes_64 = hash_bytes_odin_64
ctx.hash_file_64 = hash_file_odin_64
ctx.hash_stream_64 = hash_stream_odin_64
ctx.init = _init_odin
ctx.update = _update_odin
ctx.final = _final_odin
}
_hash_impl := _init_vtable()
// use_botan assigns the internal vtable of the hash context to use the Botan bindings
use_botan :: #force_inline proc() {
botan.assign_hash_vtable(_hash_impl, botan.HASH_SHA3)
}
// use_odin assigns the internal vtable of the hash context to use the Odin implementation
use_odin :: #force_inline proc() {
_assign_hash_vtable(_hash_impl)
}
/*
High level API
*/
@@ -80,22 +29,46 @@ hash_string_224 :: proc(data: string) -> [28]byte {
// hash_bytes_224 will hash the given input and return the
// computed hash
hash_bytes_224 :: proc(data: []byte) -> [28]byte {
_create_sha3_ctx(28)
return _hash_impl->hash_bytes_28(data)
hash: [28]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 28
_sha3.init(&ctx)
_sha3.update(&ctx, data)
_sha3.final(&ctx, hash[:])
return hash
}
// hash_stream_224 will read the stream in chunks and compute a
// hash from its contents
hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
_create_sha3_ctx(28)
return _hash_impl->hash_stream_28(s)
hash: [28]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 28
_sha3.init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = s->impl_read(buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
}
_sha3.final(&ctx, hash[:])
return hash, true
}
// hash_file_224 will read the file provided by the given handle
// and compute a hash
hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
_create_sha3_ctx(28)
return _hash_impl->hash_file_28(hd, load_at_once)
if !load_at_once {
return hash_stream_224(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_224(buf[:]), ok
}
}
return [28]byte{}, false
}
hash_224 :: proc {
@@ -114,22 +87,46 @@ hash_string_256 :: proc(data: string) -> [32]byte {
// hash_bytes_256 will hash the given input and return the
// computed hash
hash_bytes_256 :: proc(data: []byte) -> [32]byte {
_create_sha3_ctx(32)
return _hash_impl->hash_bytes_32(data)
hash: [32]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 32
_sha3.init(&ctx)
_sha3.update(&ctx, data)
_sha3.final(&ctx, hash[:])
return hash
}
// hash_stream_256 will read the stream in chunks and compute a
// hash from its contents
hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
_create_sha3_ctx(32)
return _hash_impl->hash_stream_32(s)
hash: [32]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 32
_sha3.init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = s->impl_read(buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
}
_sha3.final(&ctx, hash[:])
return hash, true
}
// hash_file_256 will read the file provided by the given handle
// and compute a hash
hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
_create_sha3_ctx(32)
return _hash_impl->hash_file_32(hd, load_at_once)
if !load_at_once {
return hash_stream_256(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_256(buf[:]), ok
}
}
return [32]byte{}, false
}
hash_256 :: proc {
@@ -148,22 +145,46 @@ hash_string_384 :: proc(data: string) -> [48]byte {
// hash_bytes_384 will hash the given input and return the
// computed hash
hash_bytes_384 :: proc(data: []byte) -> [48]byte {
_create_sha3_ctx(48)
return _hash_impl->hash_bytes_48(data)
hash: [48]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 48
_sha3.init(&ctx)
_sha3.update(&ctx, data)
_sha3.final(&ctx, hash[:])
return hash
}
// hash_stream_384 will read the stream in chunks and compute a
// hash from its contents
hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
_create_sha3_ctx(48)
return _hash_impl->hash_stream_48(s)
hash: [48]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 48
_sha3.init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = s->impl_read(buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
}
_sha3.final(&ctx, hash[:])
return hash, true
}
// hash_file_384 will read the file provided by the given handle
// and compute a hash
hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
_create_sha3_ctx(48)
return _hash_impl->hash_file_48(hd, load_at_once)
if !load_at_once {
return hash_stream_384(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_384(buf[:]), ok
}
}
return [48]byte{}, false
}
hash_384 :: proc {
@@ -182,22 +203,46 @@ hash_string_512 :: proc(data: string) -> [64]byte {
// hash_bytes_512 will hash the given input and return the
// computed hash
hash_bytes_512 :: proc(data: []byte) -> [64]byte {
_create_sha3_ctx(64)
return _hash_impl->hash_bytes_64(data)
hash: [64]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 64
_sha3.init(&ctx)
_sha3.update(&ctx, data)
_sha3.final(&ctx, hash[:])
return hash
}
// hash_stream_512 will read the stream in chunks and compute a
// hash from its contents
hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
_create_sha3_ctx(64)
return _hash_impl->hash_stream_64(s)
hash: [64]byte
ctx: _sha3.Sha3_Context
ctx.mdlen = 64
_sha3.init(&ctx)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = s->impl_read(buf)
if read > 0 {
_sha3.update(&ctx, buf[:read])
}
}
_sha3.final(&ctx, hash[:])
return hash, true
}
// hash_file_512 will read the file provided by the given handle
// and compute a hash
hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
_create_sha3_ctx(64)
return _hash_impl->hash_file_64(hd, load_at_once)
if !load_at_once {
return hash_stream_512(os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_512(buf[:]), ok
}
}
return [64]byte{}, false
}
hash_512 :: proc {
@@ -211,218 +256,16 @@ hash_512 :: proc {
Low level API
*/
init :: proc(ctx: ^_ctx.Hash_Context) {
_hash_impl->init()
Sha3_Context :: _sha3.Sha3_Context
init :: proc(ctx: ^_sha3.Sha3_Context) {
_sha3.init(ctx)
}
update :: proc(ctx: ^_ctx.Hash_Context, data: []byte) {
_hash_impl->update(data)
update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) {
_sha3.update(ctx, data)
}
final :: proc(ctx: ^_ctx.Hash_Context, hash: []byte) {
_hash_impl->final(hash)
}
hash_bytes_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, data: []byte) -> [28]byte {
hash: [28]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
_sha3.update_odin(&c, data)
_sha3.final_odin(&c, hash[:])
}
return hash
}
hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -> ([28]byte, bool) {
hash: [28]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = fs->impl_read(buf)
if read > 0 {
_sha3.update_odin(&c, buf[:read])
}
}
_sha3.final_odin(&c, hash[:])
return hash, true
} else {
return hash, false
}
}
hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
if !load_at_once {
return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_odin_28(ctx, buf[:]), ok
}
}
return [28]byte{}, false
}
hash_bytes_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, data: []byte) -> [32]byte {
hash: [32]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
_sha3.update_odin(&c, data)
_sha3.final_odin(&c, hash[:])
}
return hash
}
hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -> ([32]byte, bool) {
hash: [32]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = fs->impl_read(buf)
if read > 0 {
_sha3.update_odin(&c, buf[:read])
}
}
_sha3.final_odin(&c, hash[:])
return hash, true
} else {
return hash, false
}
}
hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
if !load_at_once {
return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_odin_32(ctx, buf[:]), ok
}
}
return [32]byte{}, false
}
hash_bytes_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, data: []byte) -> [48]byte {
hash: [48]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
_sha3.update_odin(&c, data)
_sha3.final_odin(&c, hash[:])
}
return hash
}
hash_stream_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -> ([48]byte, bool) {
hash: [48]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = fs->impl_read(buf)
if read > 0 {
_sha3.update_odin(&c, buf[:read])
}
}
_sha3.final_odin(&c, hash[:])
return hash, true
} else {
return hash, false
}
}
hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
if !load_at_once {
return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_odin_48(ctx, buf[:]), ok
}
}
return [48]byte{}, false
}
hash_bytes_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, data: []byte) -> [64]byte {
hash: [64]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
_sha3.update_odin(&c, data)
_sha3.final_odin(&c, hash[:])
}
return hash
}
hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -> ([64]byte, bool) {
hash: [64]byte
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
buf := make([]byte, 512)
defer delete(buf)
read := 1
for read > 0 {
read, _ = fs->impl_read(buf)
if read > 0 {
_sha3.update_odin(&c, buf[:read])
}
}
_sha3.final_odin(&c, hash[:])
return hash, true
} else {
return hash, false
}
}
hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
if !load_at_once {
return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
} else {
if buf, ok := os.read_entire_file(hd); ok {
return hash_bytes_odin_64(ctx, buf[:]), ok
}
}
return [64]byte{}, false
}
@(private)
_create_sha3_ctx :: #force_inline proc(mdlen: int) {
ctx: _sha3.Sha3_Context
ctx.mdlen = mdlen
_hash_impl.internal_ctx = ctx
switch mdlen {
case 28: _hash_impl.hash_size = ._28
case 32: _hash_impl.hash_size = ._32
case 48: _hash_impl.hash_size = ._48
case 64: _hash_impl.hash_size = ._64
}
}
@(private)
_init_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context) {
#partial switch ctx.hash_size {
case ._28: _create_sha3_ctx(28)
case ._32: _create_sha3_ctx(32)
case ._48: _create_sha3_ctx(48)
case ._64: _create_sha3_ctx(64)
}
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.init_odin(&c)
}
}
@(private)
_update_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, data: []byte) {
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.update_odin(&c, data)
}
}
@(private)
_final_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hash: []byte) {
if c, ok := ctx.internal_ctx.(_sha3.Sha3_Context); ok {
_sha3.final_odin(&c, hash)
}
final :: proc "contextless" (ctx: ^_sha3.Sha3_Context, hash: []byte) {
_sha3.final(ctx, hash)
}