core/crypto/aegis: Initial import

This commit is contained in:
Yawning Angel
2025-03-23 19:14:33 +09:00
parent 9fdcc4e39a
commit c2786a6dd5
11 changed files with 1441 additions and 86 deletions
+45 -2
View File
@@ -1,5 +1,6 @@
package aead
import "core:crypto/aegis"
import "core:crypto/aes"
import "core:crypto/chacha20"
import "core:crypto/chacha20poly1305"
@@ -15,7 +16,7 @@ Implementation :: union {
// MAX_TAG_SIZE is the maximum size tag that can be returned by any of the
// Algorithms supported via this package.
MAX_TAG_SIZE :: 16
MAX_TAG_SIZE :: 32
// Algorithm is the algorithm identifier associated with a given Context.
Algorithm :: enum {
@@ -25,9 +26,13 @@ Algorithm :: enum {
AES_GCM_256,
CHACHA20POLY1305,
XCHACHA20POLY1305,
AEGIS_128L,
AEGIS_128L_256, // AEGIS-128L (256-bit tag)
AEGIS_256,
AEGIS_256_256, // AEGIS-256 (256-bit tag)
}
// ALGORITM_NAMES is the Agorithm to algorithm name string.
// ALGORITM_NAMES is the Algorithm to algorithm name string.
ALGORITHM_NAMES := [Algorithm]string {
.Invalid = "Invalid",
.AES_GCM_128 = "AES-GCM-128",
@@ -35,6 +40,10 @@ ALGORITHM_NAMES := [Algorithm]string {
.AES_GCM_256 = "AES-GCM-256",
.CHACHA20POLY1305 = "chacha20poly1305",
.XCHACHA20POLY1305 = "xchacha20poly1305",
.AEGIS_128L = "AEGIS-128L",
.AEGIS_128L_256 = "AEGIS-128L-256",
.AEGIS_256 = "AEGIS-256",
.AEGIS_256_256 = "AEGIS-256-256",
}
// TAG_SIZES is the Algorithm to tag size in bytes.
@@ -45,6 +54,10 @@ TAG_SIZES := [Algorithm]int {
.AES_GCM_256 = aes.GCM_TAG_SIZE,
.CHACHA20POLY1305 = chacha20poly1305.TAG_SIZE,
.XCHACHA20POLY1305 = chacha20poly1305.TAG_SIZE,
.AEGIS_128L = aegis.TAG_SIZE_128,
.AEGIS_128L_256 = aegis.TAG_SIZE_256,
.AEGIS_256 = aegis.TAG_SIZE_128,
.AEGIS_256_256 = aegis.TAG_SIZE_256,
}
// KEY_SIZES is the Algorithm to key size in bytes.
@@ -55,6 +68,10 @@ KEY_SIZES := [Algorithm]int {
.AES_GCM_256 = aes.KEY_SIZE_256,
.CHACHA20POLY1305 = chacha20poly1305.KEY_SIZE,
.XCHACHA20POLY1305 = chacha20poly1305.KEY_SIZE,
.AEGIS_128L = aegis.KEY_SIZE_128L,
.AEGIS_128L_256 = aegis.KEY_SIZE_128L,
.AEGIS_256 = aegis.KEY_SIZE_256,
.AEGIS_256_256 = aegis.KEY_SIZE_256,
}
// IV_SIZES is the Algorithm to initialization vector size in bytes.
@@ -67,6 +84,10 @@ IV_SIZES := [Algorithm]int {
.AES_GCM_256 = aes.GCM_IV_SIZE,
.CHACHA20POLY1305 = chacha20poly1305.IV_SIZE,
.XCHACHA20POLY1305 = chacha20poly1305.XIV_SIZE,
.AEGIS_128L = aegis.IV_SIZE_128L,
.AEGIS_128L_256 = aegis.IV_SIZE_128L,
.AEGIS_256 = aegis.IV_SIZE_256,
.AEGIS_256_256 = aegis.IV_SIZE_256,
}
// Context is a concrete instantiation of a specific AEAD algorithm.
@@ -75,6 +96,7 @@ Context :: struct {
_impl: union {
aes.Context_GCM,
chacha20poly1305.Context,
aegis.Context,
},
}
@@ -86,6 +108,10 @@ _IMPL_IDS := [Algorithm]typeid {
.AES_GCM_256 = typeid_of(aes.Context_GCM),
.CHACHA20POLY1305 = typeid_of(chacha20poly1305.Context),
.XCHACHA20POLY1305 = typeid_of(chacha20poly1305.Context),
.AEGIS_128L = typeid_of(aegis.Context),
.AEGIS_128L_256 = typeid_of(aegis.Context),
.AEGIS_256 = typeid_of(aegis.Context),
.AEGIS_256_256 = typeid_of(aegis.Context),
}
// init initializes a Context with a specific AEAD Algorithm.
@@ -113,6 +139,9 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat
case .XCHACHA20POLY1305:
impl_ := impl != nil ? impl.(chacha20.Implementation) : chacha20.DEFAULT_IMPLEMENTATION
chacha20poly1305.init_xchacha(&ctx._impl.(chacha20poly1305.Context), key, impl_)
case .AEGIS_128L, .AEGIS_128L_256, .AEGIS_256, .AEGIS_256_256:
impl_ := impl != nil ? impl.(aes.Implementation) : aes.DEFAULT_IMPLEMENTATION
aegis.init(&ctx._impl.(aegis.Context), key, impl_)
case .Invalid:
panic("crypto/aead: uninitialized algorithm")
case:
@@ -127,11 +156,17 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat
//
// dst and plaintext MUST alias exactly or not at all.
seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
if len(tag) != TAG_SIZES[ctx._algo] {
panic("crypto/aead: invalid tag size")
}
switch &impl in ctx._impl {
case aes.Context_GCM:
aes.seal_gcm(&impl, dst, tag, iv, aad, plaintext)
case chacha20poly1305.Context:
chacha20poly1305.seal(&impl, dst, tag, iv, aad, plaintext)
case aegis.Context:
aegis.seal(&impl, dst, tag, iv, aad, plaintext)
case:
panic("crypto/aead: uninitialized algorithm")
}
@@ -145,11 +180,17 @@ seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
// dst and plaintext MUST alias exactly or not at all.
@(require_results)
open_ctx :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool {
if len(tag) != TAG_SIZES[ctx._algo] {
panic("crypto/aead: invalid tag size")
}
switch &impl in ctx._impl {
case aes.Context_GCM:
return aes.open_gcm(&impl, dst, iv, aad, ciphertext, tag)
case chacha20poly1305.Context:
return chacha20poly1305.open(&impl, dst, iv, aad, ciphertext, tag)
case aegis.Context:
return aegis.open(&impl, dst, iv, aad, ciphertext, tag)
case:
panic("crypto/aead: uninitialized algorithm")
}
@@ -163,6 +204,8 @@ reset :: proc(ctx: ^Context) {
aes.reset_gcm(&impl)
case chacha20poly1305.Context:
chacha20poly1305.reset(&impl)
case aegis.Context:
aegis.reset(&impl)
case:
// Calling reset repeatedly is fine.
}