1/* This file is in the public domain. */
2
3#include <sys/cdefs.h>
4__FBSDID("$FreeBSD$");
5
6#include <contrib/libb2/blake2.h>
7#include <opencrypto/xform_auth.h>
8
9extern int blake2b_init_ref(blake2b_state *S, size_t outlen);
10extern int blake2b_init_param_ref(blake2b_state *S, const blake2b_param *P);
11extern int blake2b_init_key_ref(blake2b_state *S, size_t outlen,
12    const void *key, size_t keylen);
13extern int blake2b_update_ref(blake2b_state *S, const uint8_t *in,
14    size_t inlen);
15extern int blake2b_final_ref(blake2b_state *S, uint8_t *out, size_t outlen);
16extern int blake2b_ref(uint8_t *out, const void *in, const void *key,
17    size_t outlen, size_t inlen, size_t keylen);
18
19extern int blake2s_init_ref(blake2s_state *S, size_t outlen);
20extern int blake2s_init_param_ref(blake2s_state *S, const blake2s_param *P);
21extern int blake2s_init_key_ref(blake2s_state *S, size_t outlen,
22    const void *key, size_t keylen);
23extern int blake2s_update_ref(blake2s_state *S, const uint8_t *in,
24    size_t inlen);
25extern int blake2s_final_ref(blake2s_state *S, uint8_t *out, size_t outlen);
26extern int blake2s_ref(uint8_t *out, const void *in, const void *key,
27    size_t outlen, size_t inlen, size_t keylen);
28
29struct blake2b_xform_ctx {
30	blake2b_state state;
31	uint8_t key[BLAKE2B_KEYBYTES];
32	uint16_t klen;
33};
34CTASSERT(sizeof(union authctx) >= sizeof(struct blake2b_xform_ctx));
35
36static void
37blake2b_xform_init(void *vctx)
38{
39	struct blake2b_xform_ctx *ctx = vctx;
40	int rc;
41
42	if (ctx->klen > 0)
43		rc = blake2b_init_key_ref(&ctx->state, BLAKE2B_OUTBYTES,
44		    ctx->key, ctx->klen);
45	else
46		rc = blake2b_init_ref(&ctx->state, BLAKE2B_OUTBYTES);
47	if (rc != 0)
48		panic("blake2b_init_key: invalid arguments");
49}
50
51static void
52blake2b_xform_setkey(void *vctx, const uint8_t *key, u_int klen)
53{
54	struct blake2b_xform_ctx *ctx = vctx;
55
56	if (klen > sizeof(ctx->key))
57		panic("invalid klen %u", (unsigned)klen);
58	memcpy(ctx->key, key, klen);
59	ctx->klen = klen;
60}
61
62static int
63blake2b_xform_update(void *vctx, const void *data, u_int len)
64{
65	struct blake2b_xform_ctx *ctx = vctx;
66	int rc;
67
68	rc = blake2b_update_ref(&ctx->state, data, len);
69	if (rc != 0)
70		return (EINVAL);
71	return (0);
72}
73
74static void
75blake2b_xform_final(uint8_t *out, void *vctx)
76{
77	struct blake2b_xform_ctx *ctx = vctx;
78	int rc;
79
80	rc = blake2b_final_ref(&ctx->state, out, BLAKE2B_OUTBYTES);
81	if (rc != 0)
82		panic("blake2b_final: invalid");
83}
84
85struct auth_hash auth_hash_blake2b = {
86	.type = CRYPTO_BLAKE2B,
87	.name = "Blake2b",
88	.keysize = BLAKE2B_KEYBYTES,
89	.hashsize = BLAKE2B_OUTBYTES,
90	.ctxsize = sizeof(struct blake2b_xform_ctx),
91	.Setkey = blake2b_xform_setkey,
92	.Init = blake2b_xform_init,
93	.Update = blake2b_xform_update,
94	.Final = blake2b_xform_final,
95};
96
97struct blake2s_xform_ctx {
98	blake2s_state state;
99	uint8_t key[BLAKE2S_KEYBYTES];
100	uint16_t klen;
101};
102CTASSERT(sizeof(union authctx) >= sizeof(struct blake2s_xform_ctx));
103
104static void
105blake2s_xform_init(void *vctx)
106{
107	struct blake2s_xform_ctx *ctx = vctx;
108	int rc;
109
110	if (ctx->klen > 0)
111		rc = blake2s_init_key_ref(&ctx->state, BLAKE2S_OUTBYTES,
112		    ctx->key, ctx->klen);
113	else
114		rc = blake2s_init_ref(&ctx->state, BLAKE2S_OUTBYTES);
115	if (rc != 0)
116		panic("blake2s_init_key: invalid arguments");
117}
118
119static void
120blake2s_xform_setkey(void *vctx, const uint8_t *key, u_int klen)
121{
122	struct blake2s_xform_ctx *ctx = vctx;
123
124	if (klen > sizeof(ctx->key))
125		panic("invalid klen %u", (unsigned)klen);
126	memcpy(ctx->key, key, klen);
127	ctx->klen = klen;
128}
129
130static int
131blake2s_xform_update(void *vctx, const void *data, u_int len)
132{
133	struct blake2s_xform_ctx *ctx = vctx;
134	int rc;
135
136	rc = blake2s_update_ref(&ctx->state, data, len);
137	if (rc != 0)
138		return (EINVAL);
139	return (0);
140}
141
142static void
143blake2s_xform_final(uint8_t *out, void *vctx)
144{
145	struct blake2s_xform_ctx *ctx = vctx;
146	int rc;
147
148	rc = blake2s_final_ref(&ctx->state, out, BLAKE2S_OUTBYTES);
149	if (rc != 0)
150		panic("blake2s_final: invalid");
151}
152
153struct auth_hash auth_hash_blake2s = {
154	.type = CRYPTO_BLAKE2S,
155	.name = "Blake2s",
156	.keysize = BLAKE2S_KEYBYTES,
157	.hashsize = BLAKE2S_OUTBYTES,
158	.ctxsize = sizeof(struct blake2s_xform_ctx),
159	.Setkey = blake2s_xform_setkey,
160	.Init = blake2s_xform_init,
161	.Update = blake2s_xform_update,
162	.Final = blake2s_xform_final,
163};
164