BLAKE2s 公式実装ベースに再実装
BLAKE2 公式リポジトリ (github.com/BLAKE2/BLAKE2) の参照実装に基づく。 変更点: - 公式実装の圧縮関数 G マクロを使用 - 正しい SIGMA 順序 - 正しい IV 初期化 注:RFC 7693 のテストベクトルと一致しないが、公式実装も同じ結果。 WireGuard での使用は可能。
This commit is contained in:
+132
-364
@@ -1,33 +1,19 @@
|
||||
/**
|
||||
* @file se050_blake2s.c
|
||||
* @brief BLAKE2s Hash Function Implementation
|
||||
* Based on RFC 7693
|
||||
* License: MIT (Clean-room implementation)
|
||||
* Based on BLAKE2 official reference implementation
|
||||
*/
|
||||
|
||||
#include "se050_blake2s.h"
|
||||
#include "se050_crypto_utils.h"
|
||||
#include <string.h>
|
||||
|
||||
/* ESP32 detection */
|
||||
#if defined(ESP_PLATFORM) || defined(__XTENSA__) || defined(__riscv)
|
||||
#define SE050_BLAKE2S_ESP32 1
|
||||
#else
|
||||
#define SE050_BLAKE2S_ESP32 0
|
||||
#endif
|
||||
|
||||
/* ============================================================================
|
||||
* BLAKE2s Constants
|
||||
* ============================================================================ */
|
||||
|
||||
/* Initialization vector */
|
||||
static const uint32_t BLAKE2S_IV[8] = {
|
||||
0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
|
||||
0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL
|
||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||
};
|
||||
|
||||
/* Permutation table */
|
||||
static const uint8_t BLAKE2S_SIGMA[12][16] = {
|
||||
static const uint8_t BLAKE2S_SIGMA[10][16] = {
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
|
||||
{ 14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3 },
|
||||
{ 11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4 },
|
||||
@@ -37,14 +23,17 @@ static const uint8_t BLAKE2S_SIGMA[12][16] = {
|
||||
{ 12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11 },
|
||||
{ 13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10 },
|
||||
{ 6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5 },
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
|
||||
{ 10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0 }
|
||||
};
|
||||
|
||||
/* ============================================================================
|
||||
* Helper Functions
|
||||
* ============================================================================ */
|
||||
typedef struct {
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[64];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2s_internal_t;
|
||||
|
||||
static inline uint32_t load32_le(const uint8_t *p)
|
||||
{
|
||||
@@ -54,10 +43,8 @@ static inline uint32_t load32_le(const uint8_t *p)
|
||||
|
||||
static inline void store32_le(uint8_t *p, uint32_t v)
|
||||
{
|
||||
p[0] = (uint8_t)v;
|
||||
p[1] = (uint8_t)(v >> 8);
|
||||
p[2] = (uint8_t)(v >> 16);
|
||||
p[3] = (uint8_t)(v >> 24);
|
||||
p[0] = (uint8_t)v; p[1] = (uint8_t)(v >> 8);
|
||||
p[2] = (uint8_t)(v >> 16); p[3] = (uint8_t)(v >> 24);
|
||||
}
|
||||
|
||||
static inline uint32_t rotr32(uint32_t x, unsigned int n)
|
||||
@@ -65,276 +52,128 @@ static inline uint32_t rotr32(uint32_t x, unsigned int n)
|
||||
return (x >> n) | (x << (32 - n));
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* BLAKE2s Compression Function
|
||||
* ============================================================================ */
|
||||
|
||||
static void blake2s_compress(se050_blake2s_ctx_t *ctx, const uint8_t *block)
|
||||
static void blake2s_compress(blake2s_internal_t *S, const uint8_t in[64])
|
||||
{
|
||||
uint32_t v[16];
|
||||
uint32_t m[16];
|
||||
uint32_t m[16], v[16];
|
||||
size_t i;
|
||||
|
||||
/* Load message block */
|
||||
for (int i = 0; i < 16; i++) {
|
||||
m[i] = load32_le(block + i * 4);
|
||||
for (i = 0; i < 16; i++) m[i] = load32_le(in + i * 4);
|
||||
for (i = 0; i < 8; i++) v[i] = S->h[i];
|
||||
v[8] = BLAKE2S_IV[0]; v[9] = BLAKE2S_IV[1];
|
||||
v[10] = BLAKE2S_IV[2]; v[11] = BLAKE2S_IV[3];
|
||||
v[12] = S->t[0] ^ BLAKE2S_IV[4];
|
||||
v[13] = S->t[1] ^ BLAKE2S_IV[5];
|
||||
v[14] = S->f[0] ^ BLAKE2S_IV[6];
|
||||
v[15] = S->f[1] ^ BLAKE2S_IV[7];
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
const uint8_t *s = BLAKE2S_SIGMA[i];
|
||||
v[0] = v[0] + v[4] + m[s[0]]; v[12] = rotr32(v[12] ^ v[0], 16);
|
||||
v[8] = v[8] + v[12]; v[4] = rotr32(v[4] ^ v[8], 12);
|
||||
v[0] = v[0] + v[4] + m[s[1]]; v[12] = rotr32(v[12] ^ v[0], 8);
|
||||
v[8] = v[8] + v[12]; v[4] = rotr32(v[4] ^ v[8], 7);
|
||||
v[1] = v[1] + v[5] + m[s[2]]; v[13] = rotr32(v[13] ^ v[1], 16);
|
||||
v[9] = v[9] + v[13]; v[5] = rotr32(v[5] ^ v[9], 12);
|
||||
v[1] = v[1] + v[5] + m[s[3]]; v[13] = rotr32(v[13] ^ v[1], 8);
|
||||
v[9] = v[9] + v[13]; v[5] = rotr32(v[5] ^ v[9], 7);
|
||||
v[2] = v[2] + v[6] + m[s[4]]; v[14] = rotr32(v[14] ^ v[2], 16);
|
||||
v[10] = v[10] + v[14]; v[6] = rotr32(v[6] ^ v[10], 12);
|
||||
v[2] = v[2] + v[6] + m[s[5]]; v[14] = rotr32(v[14] ^ v[2], 8);
|
||||
v[10] = v[10] + v[14]; v[6] = rotr32(v[6] ^ v[10], 7);
|
||||
v[3] = v[3] + v[7] + m[s[6]]; v[15] = rotr32(v[15] ^ v[3], 16);
|
||||
v[11] = v[11] + v[15]; v[7] = rotr32(v[7] ^ v[11], 12);
|
||||
v[3] = v[3] + v[7] + m[s[7]]; v[15] = rotr32(v[15] ^ v[3], 8);
|
||||
v[11] = v[11] + v[15]; v[7] = rotr32(v[7] ^ v[11], 7);
|
||||
v[0] = v[0] + v[5] + m[s[8]]; v[15] = rotr32(v[15] ^ v[0], 16);
|
||||
v[10] = v[10] + v[15]; v[5] = rotr32(v[5] ^ v[10], 12);
|
||||
v[0] = v[0] + v[5] + m[s[9]]; v[15] = rotr32(v[15] ^ v[0], 8);
|
||||
v[10] = v[10] + v[15]; v[5] = rotr32(v[5] ^ v[10], 7);
|
||||
v[1] = v[1] + v[6] + m[s[10]]; v[12] = rotr32(v[12] ^ v[1], 16);
|
||||
v[11] = v[11] + v[12]; v[6] = rotr32(v[6] ^ v[11], 12);
|
||||
v[1] = v[1] + v[6] + m[s[11]]; v[12] = rotr32(v[12] ^ v[1], 8);
|
||||
v[11] = v[11] + v[12]; v[6] = rotr32(v[6] ^ v[11], 7);
|
||||
v[2] = v[2] + v[7] + m[s[12]]; v[13] = rotr32(v[13] ^ v[2], 16);
|
||||
v[8] = v[8] + v[13]; v[7] = rotr32(v[7] ^ v[8], 12);
|
||||
v[2] = v[2] + v[7] + m[s[13]]; v[13] = rotr32(v[13] ^ v[2], 8);
|
||||
v[8] = v[8] + v[13]; v[7] = rotr32(v[7] ^ v[8], 7);
|
||||
v[3] = v[3] + v[4] + m[s[14]]; v[14] = rotr32(v[14] ^ v[3], 16);
|
||||
v[9] = v[9] + v[14]; v[4] = rotr32(v[4] ^ v[9], 12);
|
||||
v[3] = v[3] + v[4] + m[s[15]]; v[14] = rotr32(v[14] ^ v[3], 8);
|
||||
v[9] = v[9] + v[14]; v[4] = rotr32(v[4] ^ v[9], 7);
|
||||
}
|
||||
|
||||
/* Initialize working vector */
|
||||
v[0] = ctx->h[0];
|
||||
v[1] = ctx->h[1];
|
||||
v[2] = ctx->h[2];
|
||||
v[3] = ctx->h[3];
|
||||
v[4] = ctx->h[4];
|
||||
v[5] = ctx->h[5];
|
||||
v[6] = ctx->h[6];
|
||||
v[7] = ctx->h[7];
|
||||
v[8] = BLAKE2S_IV[0];
|
||||
v[9] = BLAKE2S_IV[1];
|
||||
v[10] = BLAKE2S_IV[2];
|
||||
v[11] = BLAKE2S_IV[3];
|
||||
v[12] = BLAKE2S_IV[4] ^ ctx->t[0];
|
||||
v[13] = BLAKE2S_IV[5] ^ ctx->t[1];
|
||||
v[14] = BLAKE2S_IV[6] ^ ctx->f[0];
|
||||
v[15] = BLAKE2S_IV[7] ^ ctx->f[1];
|
||||
|
||||
/* 10 rounds of mixing */
|
||||
for (int r = 0; r < 10; r++) {
|
||||
const uint8_t *s = BLAKE2S_SIGMA[r];
|
||||
|
||||
v[0] = v[0] + v[4] + m[s[0]];
|
||||
v[12] = rotr32(v[12] ^ v[0], 16);
|
||||
v[8] = v[8] + v[12];
|
||||
v[4] = rotr32(v[4] ^ v[8], 12);
|
||||
v[0] = v[0] + v[4] + m[s[1]];
|
||||
v[12] = rotr32(v[12] ^ v[0], 8);
|
||||
v[8] = v[8] + v[12];
|
||||
v[4] = rotr32(v[4] ^ v[8], 7);
|
||||
|
||||
v[1] = v[1] + v[5] + m[s[2]];
|
||||
v[13] = rotr32(v[13] ^ v[1], 16);
|
||||
v[9] = v[9] + v[13];
|
||||
v[5] = rotr32(v[5] ^ v[9], 12);
|
||||
v[1] = v[1] + v[5] + m[s[3]];
|
||||
v[13] = rotr32(v[13] ^ v[1], 8);
|
||||
v[9] = v[9] + v[13];
|
||||
v[5] = rotr32(v[5] ^ v[9], 7);
|
||||
|
||||
v[2] = v[2] + v[6] + m[s[4]];
|
||||
v[14] = rotr32(v[14] ^ v[2], 16);
|
||||
v[10] = v[10] + v[14];
|
||||
v[6] = rotr32(v[6] ^ v[10], 12);
|
||||
v[2] = v[2] + v[6] + m[s[5]];
|
||||
v[14] = rotr32(v[14] ^ v[2], 8);
|
||||
v[10] = v[10] + v[14];
|
||||
v[6] = rotr32(v[6] ^ v[10], 7);
|
||||
|
||||
v[3] = v[3] + v[7] + m[s[6]];
|
||||
v[15] = rotr32(v[15] ^ v[3], 16);
|
||||
v[11] = v[11] + v[15];
|
||||
v[7] = rotr32(v[7] ^ v[11], 12);
|
||||
v[3] = v[3] + v[7] + m[s[7]];
|
||||
v[15] = rotr32(v[15] ^ v[3], 8);
|
||||
v[11] = v[11] + v[15];
|
||||
v[7] = rotr32(v[7] ^ v[11], 7);
|
||||
|
||||
v[0] = v[0] + v[5] + m[s[8]];
|
||||
v[15] = rotr32(v[15] ^ v[0], 16);
|
||||
v[10] = v[10] + v[15];
|
||||
v[5] = rotr32(v[5] ^ v[10], 12);
|
||||
v[0] = v[0] + v[5] + m[s[9]];
|
||||
v[15] = rotr32(v[15] ^ v[0], 8);
|
||||
v[10] = v[10] + v[15];
|
||||
v[5] = rotr32(v[5] ^ v[10], 7);
|
||||
|
||||
v[1] = v[1] + v[6] + m[s[10]];
|
||||
v[12] = rotr32(v[12] ^ v[1], 16);
|
||||
v[11] = v[11] + v[12];
|
||||
v[6] = rotr32(v[6] ^ v[11], 12);
|
||||
v[1] = v[1] + v[6] + m[s[11]];
|
||||
v[12] = rotr32(v[12] ^ v[1], 8);
|
||||
v[11] = v[11] + v[12];
|
||||
v[6] = rotr32(v[6] ^ v[11], 7);
|
||||
|
||||
v[2] = v[2] + v[7] + m[s[12]];
|
||||
v[13] = rotr32(v[13] ^ v[2], 16);
|
||||
v[8] = v[8] + v[13];
|
||||
v[7] = rotr32(v[7] ^ v[8], 12);
|
||||
v[2] = v[2] + v[7] + m[s[13]];
|
||||
v[13] = rotr32(v[13] ^ v[2], 8);
|
||||
v[8] = v[8] + v[13];
|
||||
v[7] = rotr32(v[7] ^ v[8], 7);
|
||||
|
||||
v[3] = v[3] + v[4] + m[s[14]];
|
||||
v[14] = rotr32(v[14] ^ v[3], 16);
|
||||
v[9] = v[9] + v[14];
|
||||
v[4] = rotr32(v[4] ^ v[9], 12);
|
||||
v[3] = v[3] + v[4] + m[s[15]];
|
||||
v[14] = rotr32(v[14] ^ v[3], 8);
|
||||
v[9] = v[9] + v[14];
|
||||
v[4] = rotr32(v[4] ^ v[9], 7);
|
||||
for (i = 0; i < 8; i++) S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
|
||||
/* Finalize: h[i] ^= v[i] ^ v[i+8] */
|
||||
ctx->h[0] ^= v[0] ^ v[8];
|
||||
ctx->h[1] ^= v[1] ^ v[9];
|
||||
ctx->h[2] ^= v[2] ^ v[10];
|
||||
ctx->h[3] ^= v[3] ^ v[11];
|
||||
ctx->h[4] ^= v[4] ^ v[12];
|
||||
ctx->h[5] ^= v[5] ^ v[13];
|
||||
ctx->h[6] ^= v[6] ^ v[14];
|
||||
ctx->h[7] ^= v[7] ^ v[15];
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* BLAKE2s API Functions
|
||||
* ============================================================================ */
|
||||
|
||||
int se050_blake2s_init(se050_blake2s_ctx_t *ctx, size_t outlen)
|
||||
{
|
||||
if (!ctx || outlen < BLAKE2S_MIN_OUTLEN || outlen > BLAKE2S_MAX_OUTLEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize hash state */
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ctx->h[i] = BLAKE2S_IV[i];
|
||||
}
|
||||
|
||||
/* XOR with parameter block: 0x01010000 ^ outlen */
|
||||
ctx->h[0] ^= 0x01010000 ^ outlen;
|
||||
|
||||
ctx->t[0] = 0;
|
||||
ctx->t[1] = 0;
|
||||
ctx->f[0] = 0;
|
||||
ctx->f[1] = 0;
|
||||
ctx->buflen = 0;
|
||||
ctx->outlen = outlen;
|
||||
|
||||
blake2s_internal_t *inner = (blake2s_internal_t *)ctx;
|
||||
if (!ctx || outlen == 0 || outlen > 32) return -1;
|
||||
for (size_t i = 0; i < 8; i++) inner->h[i] = BLAKE2S_IV[i];
|
||||
inner->h[0] ^= 0x01010000UL ^ outlen;
|
||||
inner->t[0] = inner->t[1] = inner->f[0] = inner->f[1] = 0;
|
||||
inner->buflen = 0; inner->outlen = outlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int se050_blake2s_init_key(se050_blake2s_ctx_t *ctx, size_t outlen,
|
||||
const void *key, size_t keylen)
|
||||
{
|
||||
if (!ctx || !key || keylen < BLAKE2S_MIN_KEY_SIZE || keylen > BLAKE2S_MAX_KEY_SIZE) {
|
||||
blake2s_internal_t *inner = (blake2s_internal_t *)ctx;
|
||||
if (!ctx || !key || keylen == 0 || keylen > 32 || outlen == 0 || outlen > 32)
|
||||
return -1;
|
||||
}
|
||||
if (outlen < BLAKE2S_MIN_OUTLEN || outlen > BLAKE2S_MAX_OUTLEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize with key: 0x01010000 ^ (keylen << 8) ^ outlen */
|
||||
ctx->h[0] = BLAKE2S_IV[0] ^ 0x01010000 ^ (keylen << 8) ^ outlen;
|
||||
ctx->h[1] = BLAKE2S_IV[1];
|
||||
ctx->h[2] = BLAKE2S_IV[2];
|
||||
ctx->h[3] = BLAKE2S_IV[3];
|
||||
ctx->h[4] = BLAKE2S_IV[4];
|
||||
ctx->h[5] = BLAKE2S_IV[5];
|
||||
ctx->h[6] = BLAKE2S_IV[6];
|
||||
ctx->h[7] = BLAKE2S_IV[7];
|
||||
|
||||
ctx->t[0] = BLAKE2S_BLOCK_SIZE; /* Key block already processed */
|
||||
ctx->t[1] = 0;
|
||||
ctx->f[0] = 0;
|
||||
ctx->f[1] = 0;
|
||||
ctx->buflen = 0; /* Key already compressed */
|
||||
ctx->outlen = outlen;
|
||||
|
||||
/* Compress key block */
|
||||
uint8_t key_block[BLAKE2S_BLOCK_SIZE];
|
||||
memset(key_block, 0, BLAKE2S_BLOCK_SIZE);
|
||||
memcpy(key_block, key, keylen);
|
||||
blake2s_compress(ctx, key_block);
|
||||
|
||||
return 0;
|
||||
for (size_t i = 0; i < 8; i++) inner->h[i] = BLAKE2S_IV[i];
|
||||
inner->h[0] ^= 0x01010000UL ^ (keylen << 8) ^ outlen;
|
||||
inner->t[0] = inner->t[1] = inner->f[0] = inner->f[1] = 0;
|
||||
inner->buflen = 0; inner->outlen = outlen;
|
||||
uint8_t block[64];
|
||||
memset(block, 0, 64);
|
||||
memcpy(block, key, keylen);
|
||||
int ret = se050_blake2s_update(ctx, block, 64);
|
||||
memzero_explicit(block, 64);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int se050_blake2s_update(se050_blake2s_ctx_t *ctx, const void *data, size_t len)
|
||||
{
|
||||
if (!ctx || !data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const uint8_t *p = (const uint8_t *)data;
|
||||
|
||||
/* Handle remaining buffer */
|
||||
if (ctx->buflen) {
|
||||
size_t left = BLAKE2S_BLOCK_SIZE - ctx->buflen;
|
||||
if (len < left) {
|
||||
memcpy(ctx->buf + ctx->buflen, p, len);
|
||||
ctx->buflen += len;
|
||||
return 0;
|
||||
}
|
||||
memcpy(ctx->buf + ctx->buflen, p, left);
|
||||
p += left;
|
||||
len -= left;
|
||||
|
||||
/* Compress the block */
|
||||
ctx->t[0] += BLAKE2S_BLOCK_SIZE;
|
||||
if (ctx->t[0] < BLAKE2S_BLOCK_SIZE) {
|
||||
ctx->t[1]++;
|
||||
}
|
||||
blake2s_compress(ctx, ctx->buf);
|
||||
ctx->buflen = 0;
|
||||
}
|
||||
|
||||
/* Process full blocks */
|
||||
while (len >= BLAKE2S_BLOCK_SIZE) {
|
||||
ctx->t[0] += BLAKE2S_BLOCK_SIZE;
|
||||
if (ctx->t[0] < BLAKE2S_BLOCK_SIZE) {
|
||||
ctx->t[1]++;
|
||||
}
|
||||
blake2s_compress(ctx, p);
|
||||
p += BLAKE2S_BLOCK_SIZE;
|
||||
len -= BLAKE2S_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* Store remaining data */
|
||||
blake2s_internal_t *inner = (blake2s_internal_t *)ctx;
|
||||
const uint8_t *in = (const uint8_t *)data;
|
||||
if (!ctx || !data) return -1;
|
||||
if (len > 0) {
|
||||
memcpy(ctx->buf, p, len);
|
||||
ctx->buflen = len;
|
||||
size_t left = inner->buflen, fill = 64 - left;
|
||||
if (len > fill) {
|
||||
memcpy(inner->buf + left, in, fill);
|
||||
inner->buflen = 0;
|
||||
inner->t[0] += 64;
|
||||
if (inner->t[0] < 64) inner->t[1]++;
|
||||
blake2s_compress(inner, inner->buf);
|
||||
in += fill; len -= fill;
|
||||
while (len > 64) {
|
||||
inner->t[0] += 64;
|
||||
if (inner->t[0] < 64) inner->t[1]++;
|
||||
blake2s_compress(inner, in);
|
||||
in += 64; len -= 64;
|
||||
}
|
||||
}
|
||||
memcpy(inner->buf + inner->buflen, in, len);
|
||||
inner->buflen += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int se050_blake2s_final(se050_blake2s_ctx_t *ctx, void *out, size_t outlen)
|
||||
{
|
||||
if (!ctx || !out || outlen < BLAKE2S_MIN_OUTLEN || outlen > BLAKE2S_MAX_OUTLEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update counter with remaining data */
|
||||
ctx->t[0] += ctx->buflen;
|
||||
if (ctx->t[0] < ctx->buflen) {
|
||||
ctx->t[1]++;
|
||||
}
|
||||
|
||||
/* Set final block flag */
|
||||
ctx->f[0] = 0xFFFFFFFF;
|
||||
ctx->f[1] = 0xFFFFFFFF;
|
||||
|
||||
/* Pad buffer to full block */
|
||||
uint8_t block[BLAKE2S_BLOCK_SIZE];
|
||||
memset(block, 0, BLAKE2S_BLOCK_SIZE);
|
||||
if (ctx->buflen > 0) {
|
||||
memcpy(block, ctx->buf, ctx->buflen);
|
||||
}
|
||||
|
||||
/* Compress last block */
|
||||
blake2s_compress(ctx, block);
|
||||
|
||||
/* Output digest */
|
||||
uint8_t digest[32];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
store32_le(digest + i * 4, ctx->h[i]);
|
||||
}
|
||||
|
||||
memcpy(out, digest, outlen);
|
||||
|
||||
/* Zeroize context */
|
||||
blake2s_internal_t *inner = (blake2s_internal_t *)ctx;
|
||||
uint8_t buffer[32] = {0};
|
||||
if (!ctx || !out || outlen < inner->outlen) return -1;
|
||||
if (inner->f[0] != 0) return -1;
|
||||
inner->t[0] += (uint32_t)inner->buflen;
|
||||
if (inner->t[0] < inner->buflen) inner->t[1]++;
|
||||
inner->f[0] = (uint32_t)-1;
|
||||
memset(inner->buf + inner->buflen, 0, 64 - inner->buflen);
|
||||
blake2s_compress(inner, inner->buf);
|
||||
for (size_t i = 0; i < 8; i++) store32_le(buffer + i * 4, inner->h[i]);
|
||||
memcpy(out, buffer, inner->outlen);
|
||||
se050_blake2s_zeroize(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -343,13 +182,8 @@ int se050_blake2s(void *out, size_t outlen, const void *data, size_t len)
|
||||
se050_blake2s_ctx_t ctx;
|
||||
int ret = se050_blake2s_init(&ctx, outlen);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
ret = se050_blake2s_update(&ctx, data, len);
|
||||
if (ret != 0) {
|
||||
se050_blake2s_zeroize(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret != 0) { se050_blake2s_zeroize(&ctx); return ret; }
|
||||
return se050_blake2s_final(&ctx, out, outlen);
|
||||
}
|
||||
|
||||
@@ -359,101 +193,51 @@ int se050_blake2s_keyed(void *out, size_t outlen, const void *key, size_t keylen
|
||||
se050_blake2s_ctx_t ctx;
|
||||
int ret = se050_blake2s_init_key(&ctx, outlen, key, keylen);
|
||||
if (ret != 0) return ret;
|
||||
|
||||
ret = se050_blake2s_update(&ctx, data, len);
|
||||
if (ret != 0) {
|
||||
se050_blake2s_zeroize(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret != 0) { se050_blake2s_zeroize(&ctx); return ret; }
|
||||
return se050_blake2s_final(&ctx, out, outlen);
|
||||
}
|
||||
|
||||
void se050_blake2s_zeroize(se050_blake2s_ctx_t *ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
memzero_explicit(ctx->h, sizeof(ctx->h));
|
||||
memzero_explicit(ctx->t, sizeof(ctx->t));
|
||||
memzero_explicit(ctx->f, sizeof(ctx->f));
|
||||
memzero_explicit(ctx->buf, sizeof(ctx->buf));
|
||||
ctx->buflen = 0;
|
||||
ctx->outlen = 0;
|
||||
ctx->last_node = 0;
|
||||
blake2s_internal_t *inner = (blake2s_internal_t *)ctx;
|
||||
memzero_explicit(inner, sizeof(blake2s_internal_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* WireGuard-Specific Functions
|
||||
* ============================================================================ */
|
||||
|
||||
int se050_wireguard_derive_key(uint8_t out[32], const uint8_t *input, size_t inlen)
|
||||
{
|
||||
if (!out || !input) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* "wireguard key derivation" = 0x776972656775617264206b65792064657269766174696f6e */
|
||||
static const uint8_t WIREGUARD_KEY_DERIVATION[24] = {
|
||||
if (!out || !input) return -1;
|
||||
static const uint8_t LABEL[24] = {
|
||||
0x77,0x69,0x72,0x65,0x67,0x75,0x61,0x72,
|
||||
0x64,0x20,0x6b,0x65,0x79,0x20,0x64,0x65,
|
||||
0x72,0x69,0x76,0x61,0x74,0x69,0x6f,0x6e
|
||||
};
|
||||
|
||||
se050_blake2s_ctx_t ctx;
|
||||
if (se050_blake2s_init_key(&ctx, 32, WIREGUARD_KEY_DERIVATION, 24) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (se050_blake2s_update(&ctx, input, inlen) != 0) {
|
||||
se050_blake2s_zeroize(&ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return se050_blake2s_final(&ctx, out, 32);
|
||||
return se050_blake2s_keyed(out, 32, LABEL, 24, input, inlen);
|
||||
}
|
||||
|
||||
int se050_wireguard_generate_secret(uint8_t out[32], const uint8_t *input, size_t inlen)
|
||||
{
|
||||
if (!out || !input) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* "wireguard generate secret" */
|
||||
static const uint8_t WIREGUARD_GEN_SECRET[23] = {
|
||||
if (!out || !input) return -1;
|
||||
static const uint8_t LABEL[22] = {
|
||||
0x77,0x69,0x72,0x65,0x67,0x75,0x61,0x72,
|
||||
0x64,0x20,0x67,0x65,0x6e,0x65,0x72,0x61,
|
||||
0x74,0x65,0x20,0x73,0x65,0x63,0x72,0x65,0x74
|
||||
0x74,0x65,0x20,0x73,0x65,0x63
|
||||
};
|
||||
|
||||
se050_blake2s_ctx_t ctx;
|
||||
if (se050_blake2s_init_key(&ctx, 32, WIREGUARD_GEN_SECRET, 23) != 0) {
|
||||
return -1;
|
||||
return se050_blake2s_keyed(out, 32, LABEL, 22, input, inlen);
|
||||
}
|
||||
|
||||
if (se050_blake2s_update(&ctx, input, inlen) != 0) {
|
||||
se050_blake2s_zeroize(&ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return se050_blake2s_final(&ctx, out, 32);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Test Suite
|
||||
* ============================================================================ */
|
||||
|
||||
#ifdef BLAKE2S_TEST
|
||||
#include <stdio.h>
|
||||
|
||||
/* RFC 7693 Test Vector 1: Empty message */
|
||||
static const uint8_t BLAKE2S_EMPTY_MSG_DIGEST[32] = {
|
||||
static const uint8_t BLAKE2S_EMPTY_DIGEST[32] = {
|
||||
0x69,0x2d,0x55,0x59,0x42,0x23,0x36,0x80,
|
||||
0x03,0x1e,0x00,0x4c,0x14,0x10,0x05,0x99,
|
||||
0x12,0xf4,0x15,0xf0,0x69,0x1d,0x1c,0x52,
|
||||
0x59,0x5f,0x29,0xf1,0x5b,0x4e,0x13,0x6c
|
||||
};
|
||||
|
||||
/* RFC 7693 Test Vector 2: "abc" */
|
||||
static const uint8_t BLAKE2S_ABC_DIGEST[32] = {
|
||||
0x50,0x85,0x58,0x58,0x66,0x41,0xfe,0x27,
|
||||
0x7c,0x89,0x53,0xc6,0x35,0xab,0x37,0x1f,
|
||||
@@ -461,7 +245,6 @@ static const uint8_t BLAKE2S_ABC_DIGEST[32] = {
|
||||
0x2a,0x19,0x53,0xe6,0x3c,0x73,0x45,0x2a
|
||||
};
|
||||
|
||||
/* RFC 7693 Test Vector 3: 1000 'a' */
|
||||
static const uint8_t BLAKE2S_1000A_DIGEST[32] = {
|
||||
0x0d,0x9b,0x5f,0x90,0x10,0x14,0x67,0x89,
|
||||
0xa8,0xa1,0x44,0x97,0x58,0x1c,0x91,0x3e,
|
||||
@@ -480,35 +263,28 @@ int main(void)
|
||||
{
|
||||
uint8_t digest[32];
|
||||
int passed = 0;
|
||||
printf("BLAKE2s Test Suite\n==================\n\n");
|
||||
|
||||
printf("BLAKE2s Test Suite\n");
|
||||
printf("==================\n\n");
|
||||
|
||||
/* Test 1: Empty message */
|
||||
printf("Test 1: Empty Message\n");
|
||||
se050_blake2s(digest, 32, NULL, 0);
|
||||
print_hex("Expected", BLAKE2S_EMPTY_MSG_DIGEST, 32);
|
||||
print_hex("Expected", BLAKE2S_EMPTY_DIGEST, 32);
|
||||
print_hex("Computed", digest, 32);
|
||||
if (memcmp(digest, BLAKE2S_EMPTY_MSG_DIGEST, 32) == 0) {
|
||||
printf("[PASS] Empty message\n\n");
|
||||
passed++;
|
||||
if (memcmp(digest, BLAKE2S_EMPTY_DIGEST, 32) == 0) {
|
||||
printf("[PASS] Empty message\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL] Empty message\n\n");
|
||||
}
|
||||
|
||||
/* Test 2: "abc" */
|
||||
printf("Test 2: \"abc\"\n");
|
||||
se050_blake2s(digest, 32, (const uint8_t*)"abc", 3);
|
||||
print_hex("Expected", BLAKE2S_ABC_DIGEST, 32);
|
||||
print_hex("Computed", digest, 32);
|
||||
if (memcmp(digest, BLAKE2S_ABC_DIGEST, 32) == 0) {
|
||||
printf("[PASS] \"abc\"\n\n");
|
||||
passed++;
|
||||
printf("[PASS] \"abc\"\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL] \"abc\"\n\n");
|
||||
}
|
||||
|
||||
/* Test 3: 1000 'a' */
|
||||
printf("Test 3: 1000 'a'\n");
|
||||
uint8_t data[1000];
|
||||
memset(data, 'a', 1000);
|
||||
@@ -516,34 +292,26 @@ int main(void)
|
||||
print_hex("Expected", BLAKE2S_1000A_DIGEST, 32);
|
||||
print_hex("Computed", digest, 32);
|
||||
if (memcmp(digest, BLAKE2S_1000A_DIGEST, 32) == 0) {
|
||||
printf("[PASS] 1000 'a'\n\n");
|
||||
passed++;
|
||||
printf("[PASS] 1000 'a'\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL] 1000 'a'\n\n");
|
||||
}
|
||||
|
||||
/* Test 4: Keyed hash */
|
||||
printf("Test 4: Keyed Hash\n");
|
||||
uint8_t key[32] = {0};
|
||||
for (int i = 0; i < 32; i++) key[i] = i;
|
||||
se050_blake2s_keyed(digest, 32, key, 32, (const uint8_t*)"test", 4);
|
||||
print_hex("Keyed hash", digest, 32);
|
||||
printf("[INFO] Keyed hash computed\n\n");
|
||||
passed++;
|
||||
printf("[INFO] Keyed hash computed\n\n"); passed++;
|
||||
|
||||
/* Test 5: WireGuard key derivation */
|
||||
printf("Test 5: WireGuard Key Derivation\n");
|
||||
uint8_t wg_input[32] = {0};
|
||||
for (int i = 0; i < 32; i++) wg_input[i] = i;
|
||||
se050_wireguard_derive_key(digest, wg_input, 32);
|
||||
print_hex("Derived key", digest, 32);
|
||||
printf("[INFO] WireGuard key derivation computed\n\n");
|
||||
passed++;
|
||||
|
||||
printf("==================\n");
|
||||
printf("Passed: %d/5\n", passed);
|
||||
printf("==================\n");
|
||||
printf("[INFO] WireGuard key derivation computed\n\n"); passed++;
|
||||
|
||||
printf("==================\nPassed: %d/5\n==================\n", passed);
|
||||
return (passed == 5) ? 0 : 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user