Line data Source code
1 : #include "fd_merlin.h"
2 : #include "../../../../../ballet/keccak256/fd_keccak256_private.h"
3 :
4 : /* Derived from https://github.com/hdevalence/libmerlin */
5 :
6 : /* Strobe-128 Internals */
7 :
8 531381 : #define STROBE_R 166
9 2259 : #define FLAG_I (1)
10 19017 : #define FLAG_A (1 << 1)
11 21276 : #define FLAG_C (1 << 2)
12 : #define FLAG_T (1 << 3)
13 9792 : #define FLAG_M (1 << 4)
14 19017 : #define FLAG_K (1 << 5)
15 :
16 : static inline void
17 3693 : strobe128_run_f( fd_merlin_strobe128_t * ctx ) {
18 3693 : ctx->state_bytes[ctx->pos] ^= ctx->pos_begin;
19 3693 : ctx->state_bytes[ctx->pos + 1] ^= 0x04;
20 3693 : ctx->state_bytes[STROBE_R + 1] ^= 0x80;
21 3693 : fd_keccak256_core( ctx->state );
22 3693 : ctx->pos = 0;
23 3693 : ctx->pos_begin = 0;
24 3693 : }
25 :
26 : static void
27 : strobe128_absorb( fd_merlin_strobe128_t * ctx,
28 : uchar const * data,
29 45000 : ulong const data_len) {
30 428112 : for ( ulong i=0; i<data_len; i++ ) {
31 383112 : ctx->state_bytes[ctx->pos] ^= data[i];
32 383112 : ctx->pos++;
33 383112 : if (ctx->pos == STROBE_R) {
34 1434 : strobe128_run_f(ctx);
35 1434 : }
36 383112 : }
37 45000 : }
38 :
39 : static void
40 : strobe128_squeeze( fd_merlin_strobe128_t * ctx,
41 : uchar * data,
42 2259 : ulong const data_len) {
43 146835 : for ( ulong i=0; i<data_len; i++ ) {
44 144576 : data[i] = ctx->state_bytes[ctx->pos];
45 144576 : ctx->state_bytes[ctx->pos] = 0;
46 144576 : ctx->pos++;
47 144576 : if (ctx->pos == STROBE_R) {
48 0 : strobe128_run_f(ctx);
49 0 : }
50 144576 : }
51 2259 : }
52 :
53 : static void
54 : strobe128_begin_op( fd_merlin_strobe128_t * ctx,
55 19017 : uchar flags ) {
56 : /* Note: this implementation cuts some corners, see code below.
57 : Our implementation of Merlin doesn't use these features. */
58 :
59 : /*
60 : if (more) {
61 : // Changing flags while continuing is illegal
62 : assert(ctx->cur_flags == flags);
63 : return;
64 : }
65 :
66 : // T flag is not supported
67 : assert(!(flags & FLAG_T));
68 : */
69 :
70 19017 : uchar old_begin = ctx->pos_begin;
71 19017 : ctx->pos_begin = (uchar)(ctx->pos + 1);
72 19017 : ctx->cur_flags = flags;
73 :
74 19017 : uchar data[2] = { old_begin, flags };
75 19017 : strobe128_absorb( ctx, data, 2 );
76 :
77 : /* Force running the permutation if C or K is set. */
78 19017 : uchar force_f = 0 != (flags & (FLAG_C | FLAG_K));
79 :
80 19017 : if (force_f && ctx->pos != 0) {
81 2259 : strobe128_run_f(ctx);
82 2259 : }
83 19017 : }
84 :
85 : /* Strobe-128 */
86 :
87 : static inline void
88 : strobe128_meta_ad( fd_merlin_strobe128_t * ctx,
89 : uchar const * data,
90 : ulong data_len,
91 19017 : uchar more ) {
92 19017 : if ( more==0 ) {
93 9792 : strobe128_begin_op( ctx, FLAG_M | FLAG_A );
94 9792 : }
95 19017 : strobe128_absorb( ctx, data, data_len );
96 19017 : }
97 :
98 : static inline void
99 : strobe128_ad(fd_merlin_strobe128_t * ctx,
100 : uchar const * data,
101 : ulong const data_len,
102 6966 : uchar more) {
103 6966 : if ( more==0 ) {
104 6966 : strobe128_begin_op( ctx, FLAG_A );
105 6966 : }
106 6966 : strobe128_absorb( ctx, data, data_len );
107 6966 : }
108 :
109 : static inline void
110 : strobe128_prf( fd_merlin_strobe128_t * ctx,
111 : uchar * data,
112 : ulong const data_len,
113 2259 : uchar more ) {
114 2259 : if ( more==0 ) {
115 2259 : strobe128_begin_op(ctx, FLAG_I | FLAG_A | FLAG_C );
116 2259 : }
117 2259 : strobe128_squeeze(ctx, data, data_len);
118 2259 : }
119 :
120 : static inline void
121 : strobe128_init( fd_merlin_strobe128_t * ctx,
122 : uchar const * label,
123 567 : ulong const label_len ) {
124 567 : uchar init[18] = {
125 567 : 1, 168, 1, 0, 1, 96, 83, 84, 82,
126 567 : 79, 66, 69, 118, 49, 46, 48, 46, 50,
127 567 : };
128 567 : fd_memset( ctx->state_bytes, 0, 200 );
129 567 : fd_memcpy( ctx->state_bytes, init, 18 );
130 567 : fd_keccak256_core( ctx->state );
131 567 : ctx->pos = 0;
132 567 : ctx->pos_begin = 0;
133 567 : ctx->cur_flags = 0;
134 :
135 567 : strobe128_meta_ad( ctx, label, label_len, 0 );
136 567 : }
137 :
138 : /* Merlin */
139 :
140 : void
141 : fd_merlin_transcript_init( fd_merlin_transcript_t * mctx,
142 : char const * const label,
143 567 : uint const label_len ) {
144 567 : strobe128_init(&mctx->sctx, (uchar *)FD_MERLIN_LITERAL("Merlin v1.0"));
145 567 : fd_merlin_transcript_append_message(mctx, FD_MERLIN_LITERAL("dom-sep"), (uchar *)label, label_len);
146 567 : }
147 :
148 : void
149 : fd_merlin_transcript_append_message( fd_merlin_transcript_t * mctx,
150 : char const * const label,
151 : uint const label_len,
152 : uchar const * message,
153 6966 : uint const message_len ) {
154 6966 : strobe128_meta_ad(&mctx->sctx, (uchar *)label, label_len, 0);
155 6966 : strobe128_meta_ad(&mctx->sctx, (uchar *)&message_len, 4, 1);
156 6966 : strobe128_ad(&mctx->sctx, message, message_len, 0);
157 6966 : }
158 :
159 : inline void
160 : fd_merlin_transcript_append_u64( fd_merlin_transcript_t * mctx,
161 : char const * const label,
162 : uint const label_len,
163 474 : ulong const message_u64 ) {
164 474 : fd_merlin_transcript_append_message( mctx, label, label_len, (uchar *)&message_u64, 8 );
165 474 : }
166 :
167 : void
168 : fd_merlin_transcript_challenge_bytes( fd_merlin_transcript_t * mctx,
169 : char const * const label,
170 : uint const label_len,
171 : uchar * buffer,
172 2259 : uint const buffer_len ) {
173 2259 : strobe128_meta_ad(&mctx->sctx, (uchar *)label, label_len, 0);
174 2259 : strobe128_meta_ad(&mctx->sctx, (uchar *)&buffer_len, 4, 1);
175 2259 : strobe128_prf(&mctx->sctx, buffer, buffer_len, 0);
176 2259 : }
|