@@ -38,7 +38,7 @@ int crypto_poly1305_init(struct shash_desc *desc)
38
38
{
39
39
struct poly1305_desc_ctx * dctx = shash_desc_ctx (desc );
40
40
41
- memset ( dctx -> h . h , 0 , sizeof ( dctx -> h . h ) );
41
+ poly1305_core_init ( & dctx -> h );
42
42
dctx -> buflen = 0 ;
43
43
dctx -> rset = false;
44
44
dctx -> sset = false;
@@ -47,23 +47,16 @@ int crypto_poly1305_init(struct shash_desc *desc)
47
47
}
48
48
EXPORT_SYMBOL_GPL (crypto_poly1305_init );
49
49
50
- static void poly1305_setrkey (struct poly1305_desc_ctx * dctx , const u8 * key )
50
+ void poly1305_core_setkey (struct poly1305_key * key , const u8 * raw_key )
51
51
{
52
52
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
53
- dctx -> r .r [0 ] = (get_unaligned_le32 (key + 0 ) >> 0 ) & 0x3ffffff ;
54
- dctx -> r .r [1 ] = (get_unaligned_le32 (key + 3 ) >> 2 ) & 0x3ffff03 ;
55
- dctx -> r .r [2 ] = (get_unaligned_le32 (key + 6 ) >> 4 ) & 0x3ffc0ff ;
56
- dctx -> r .r [3 ] = (get_unaligned_le32 (key + 9 ) >> 6 ) & 0x3f03fff ;
57
- dctx -> r .r [4 ] = (get_unaligned_le32 (key + 12 ) >> 8 ) & 0x00fffff ;
58
- }
59
-
60
- static void poly1305_setskey (struct poly1305_desc_ctx * dctx , const u8 * key )
61
- {
62
- dctx -> s [0 ] = get_unaligned_le32 (key + 0 );
63
- dctx -> s [1 ] = get_unaligned_le32 (key + 4 );
64
- dctx -> s [2 ] = get_unaligned_le32 (key + 8 );
65
- dctx -> s [3 ] = get_unaligned_le32 (key + 12 );
53
+ key -> r [0 ] = (get_unaligned_le32 (raw_key + 0 ) >> 0 ) & 0x3ffffff ;
54
+ key -> r [1 ] = (get_unaligned_le32 (raw_key + 3 ) >> 2 ) & 0x3ffff03 ;
55
+ key -> r [2 ] = (get_unaligned_le32 (raw_key + 6 ) >> 4 ) & 0x3ffc0ff ;
56
+ key -> r [3 ] = (get_unaligned_le32 (raw_key + 9 ) >> 6 ) & 0x3f03fff ;
57
+ key -> r [4 ] = (get_unaligned_le32 (raw_key + 12 ) >> 8 ) & 0x00fffff ;
66
58
}
59
+ EXPORT_SYMBOL_GPL (poly1305_core_setkey );
67
60
68
61
/*
69
62
* Poly1305 requires a unique key for each tag, which implies that we can't set
@@ -75,13 +68,16 @@ unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
75
68
{
76
69
if (!dctx -> sset ) {
77
70
if (!dctx -> rset && srclen >= POLY1305_BLOCK_SIZE ) {
78
- poly1305_setrkey ( dctx , src );
71
+ poly1305_core_setkey ( & dctx -> r , src );
79
72
src += POLY1305_BLOCK_SIZE ;
80
73
srclen -= POLY1305_BLOCK_SIZE ;
81
74
dctx -> rset = true;
82
75
}
83
76
if (srclen >= POLY1305_BLOCK_SIZE ) {
84
- poly1305_setskey (dctx , src );
77
+ dctx -> s [0 ] = get_unaligned_le32 (src + 0 );
78
+ dctx -> s [1 ] = get_unaligned_le32 (src + 4 );
79
+ dctx -> s [2 ] = get_unaligned_le32 (src + 8 );
80
+ dctx -> s [3 ] = get_unaligned_le32 (src + 12 );
85
81
src += POLY1305_BLOCK_SIZE ;
86
82
srclen -= POLY1305_BLOCK_SIZE ;
87
83
dctx -> sset = true;
@@ -91,41 +87,37 @@ unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
91
87
}
92
88
EXPORT_SYMBOL_GPL (crypto_poly1305_setdesckey );
93
89
94
- static unsigned int poly1305_blocks (struct poly1305_desc_ctx * dctx ,
95
- const u8 * src , unsigned int srclen ,
96
- u32 hibit )
90
+ static void poly1305_blocks_internal (struct poly1305_state * state ,
91
+ const struct poly1305_key * key ,
92
+ const void * src , unsigned int nblocks ,
93
+ u32 hibit )
97
94
{
98
95
u32 r0 , r1 , r2 , r3 , r4 ;
99
96
u32 s1 , s2 , s3 , s4 ;
100
97
u32 h0 , h1 , h2 , h3 , h4 ;
101
98
u64 d0 , d1 , d2 , d3 , d4 ;
102
- unsigned int datalen ;
103
99
104
- if (unlikely (!dctx -> sset )) {
105
- datalen = crypto_poly1305_setdesckey (dctx , src , srclen );
106
- src += srclen - datalen ;
107
- srclen = datalen ;
108
- }
100
+ if (!nblocks )
101
+ return ;
109
102
110
- r0 = dctx -> r . r [0 ];
111
- r1 = dctx -> r . r [1 ];
112
- r2 = dctx -> r . r [2 ];
113
- r3 = dctx -> r . r [3 ];
114
- r4 = dctx -> r . r [4 ];
103
+ r0 = key -> r [0 ];
104
+ r1 = key -> r [1 ];
105
+ r2 = key -> r [2 ];
106
+ r3 = key -> r [3 ];
107
+ r4 = key -> r [4 ];
115
108
116
109
s1 = r1 * 5 ;
117
110
s2 = r2 * 5 ;
118
111
s3 = r3 * 5 ;
119
112
s4 = r4 * 5 ;
120
113
121
- h0 = dctx -> h .h [0 ];
122
- h1 = dctx -> h .h [1 ];
123
- h2 = dctx -> h .h [2 ];
124
- h3 = dctx -> h .h [3 ];
125
- h4 = dctx -> h .h [4 ];
126
-
127
- while (likely (srclen >= POLY1305_BLOCK_SIZE )) {
114
+ h0 = state -> h [0 ];
115
+ h1 = state -> h [1 ];
116
+ h2 = state -> h [2 ];
117
+ h3 = state -> h [3 ];
118
+ h4 = state -> h [4 ];
128
119
120
+ do {
129
121
/* h += m[i] */
130
122
h0 += (get_unaligned_le32 (src + 0 ) >> 0 ) & 0x3ffffff ;
131
123
h1 += (get_unaligned_le32 (src + 3 ) >> 2 ) & 0x3ffffff ;
@@ -154,16 +146,36 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
154
146
h1 += h0 >> 26 ; h0 = h0 & 0x3ffffff ;
155
147
156
148
src += POLY1305_BLOCK_SIZE ;
157
- srclen -= POLY1305_BLOCK_SIZE ;
158
- }
149
+ } while (-- nblocks );
159
150
160
- dctx -> h .h [0 ] = h0 ;
161
- dctx -> h .h [1 ] = h1 ;
162
- dctx -> h .h [2 ] = h2 ;
163
- dctx -> h .h [3 ] = h3 ;
164
- dctx -> h .h [4 ] = h4 ;
151
+ state -> h [0 ] = h0 ;
152
+ state -> h [1 ] = h1 ;
153
+ state -> h [2 ] = h2 ;
154
+ state -> h [3 ] = h3 ;
155
+ state -> h [4 ] = h4 ;
156
+ }
165
157
166
- return srclen ;
158
+ void poly1305_core_blocks (struct poly1305_state * state ,
159
+ const struct poly1305_key * key ,
160
+ const void * src , unsigned int nblocks )
161
+ {
162
+ poly1305_blocks_internal (state , key , src , nblocks , 1 << 24 );
163
+ }
164
+ EXPORT_SYMBOL_GPL (poly1305_core_blocks );
165
+
166
+ static void poly1305_blocks (struct poly1305_desc_ctx * dctx ,
167
+ const u8 * src , unsigned int srclen , u32 hibit )
168
+ {
169
+ unsigned int datalen ;
170
+
171
+ if (unlikely (!dctx -> sset )) {
172
+ datalen = crypto_poly1305_setdesckey (dctx , src , srclen );
173
+ src += srclen - datalen ;
174
+ srclen = datalen ;
175
+ }
176
+
177
+ poly1305_blocks_internal (& dctx -> h , & dctx -> r ,
178
+ src , srclen / POLY1305_BLOCK_SIZE , hibit );
167
179
}
168
180
169
181
int crypto_poly1305_update (struct shash_desc * desc ,
@@ -187,9 +199,9 @@ int crypto_poly1305_update(struct shash_desc *desc,
187
199
}
188
200
189
201
if (likely (srclen >= POLY1305_BLOCK_SIZE )) {
190
- bytes = poly1305_blocks (dctx , src , srclen , 1 << 24 );
191
- src += srclen - bytes ;
192
- srclen = bytes ;
202
+ poly1305_blocks (dctx , src , srclen , 1 << 24 );
203
+ src += srclen - ( srclen % POLY1305_BLOCK_SIZE ) ;
204
+ srclen %= POLY1305_BLOCK_SIZE ;
193
205
}
194
206
195
207
if (unlikely (srclen )) {
@@ -201,30 +213,18 @@ int crypto_poly1305_update(struct shash_desc *desc,
201
213
}
202
214
EXPORT_SYMBOL_GPL (crypto_poly1305_update );
203
215
204
- int crypto_poly1305_final ( struct shash_desc * desc , u8 * dst )
216
+ void poly1305_core_emit ( const struct poly1305_state * state , void * dst )
205
217
{
206
- struct poly1305_desc_ctx * dctx = shash_desc_ctx (desc );
207
218
u32 h0 , h1 , h2 , h3 , h4 ;
208
219
u32 g0 , g1 , g2 , g3 , g4 ;
209
220
u32 mask ;
210
- u64 f = 0 ;
211
-
212
- if (unlikely (!dctx -> sset ))
213
- return - ENOKEY ;
214
-
215
- if (unlikely (dctx -> buflen )) {
216
- dctx -> buf [dctx -> buflen ++ ] = 1 ;
217
- memset (dctx -> buf + dctx -> buflen , 0 ,
218
- POLY1305_BLOCK_SIZE - dctx -> buflen );
219
- poly1305_blocks (dctx , dctx -> buf , POLY1305_BLOCK_SIZE , 0 );
220
- }
221
221
222
222
/* fully carry h */
223
- h0 = dctx -> h . h [0 ];
224
- h1 = dctx -> h . h [1 ];
225
- h2 = dctx -> h . h [2 ];
226
- h3 = dctx -> h . h [3 ];
227
- h4 = dctx -> h . h [4 ];
223
+ h0 = state -> h [0 ];
224
+ h1 = state -> h [1 ];
225
+ h2 = state -> h [2 ];
226
+ h3 = state -> h [3 ];
227
+ h4 = state -> h [4 ];
228
228
229
229
h2 += (h1 >> 26 ); h1 = h1 & 0x3ffffff ;
230
230
h3 += (h2 >> 26 ); h2 = h2 & 0x3ffffff ;
@@ -254,16 +254,40 @@ int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
254
254
h4 = (h4 & mask ) | g4 ;
255
255
256
256
/* h = h % (2^128) */
257
- h0 = (h0 >> 0 ) | (h1 << 26 );
258
- h1 = (h1 >> 6 ) | (h2 << 20 );
259
- h2 = (h2 >> 12 ) | (h3 << 14 );
260
- h3 = (h3 >> 18 ) | (h4 << 8 );
257
+ put_unaligned_le32 ((h0 >> 0 ) | (h1 << 26 ), dst + 0 );
258
+ put_unaligned_le32 ((h1 >> 6 ) | (h2 << 20 ), dst + 4 );
259
+ put_unaligned_le32 ((h2 >> 12 ) | (h3 << 14 ), dst + 8 );
260
+ put_unaligned_le32 ((h3 >> 18 ) | (h4 << 8 ), dst + 12 );
261
+ }
262
+ EXPORT_SYMBOL_GPL (poly1305_core_emit );
263
+
264
+ int crypto_poly1305_final (struct shash_desc * desc , u8 * dst )
265
+ {
266
+ struct poly1305_desc_ctx * dctx = shash_desc_ctx (desc );
267
+ __le32 digest [4 ];
268
+ u64 f = 0 ;
269
+
270
+ if (unlikely (!dctx -> sset ))
271
+ return - ENOKEY ;
272
+
273
+ if (unlikely (dctx -> buflen )) {
274
+ dctx -> buf [dctx -> buflen ++ ] = 1 ;
275
+ memset (dctx -> buf + dctx -> buflen , 0 ,
276
+ POLY1305_BLOCK_SIZE - dctx -> buflen );
277
+ poly1305_blocks (dctx , dctx -> buf , POLY1305_BLOCK_SIZE , 0 );
278
+ }
279
+
280
+ poly1305_core_emit (& dctx -> h , digest );
261
281
262
282
/* mac = (h + s) % (2^128) */
263
- f = (f >> 32 ) + h0 + dctx -> s [0 ]; put_unaligned_le32 (f , dst + 0 );
264
- f = (f >> 32 ) + h1 + dctx -> s [1 ]; put_unaligned_le32 (f , dst + 4 );
265
- f = (f >> 32 ) + h2 + dctx -> s [2 ]; put_unaligned_le32 (f , dst + 8 );
266
- f = (f >> 32 ) + h3 + dctx -> s [3 ]; put_unaligned_le32 (f , dst + 12 );
283
+ f = (f >> 32 ) + le32_to_cpu (digest [0 ]) + dctx -> s [0 ];
284
+ put_unaligned_le32 (f , dst + 0 );
285
+ f = (f >> 32 ) + le32_to_cpu (digest [1 ]) + dctx -> s [1 ];
286
+ put_unaligned_le32 (f , dst + 4 );
287
+ f = (f >> 32 ) + le32_to_cpu (digest [2 ]) + dctx -> s [2 ];
288
+ put_unaligned_le32 (f , dst + 8 );
289
+ f = (f >> 32 ) + le32_to_cpu (digest [3 ]) + dctx -> s [3 ];
290
+ put_unaligned_le32 (f , dst + 12 );
267
291
268
292
return 0 ;
269
293
}
0 commit comments