MagickCore 7.0.10
chacha.c
Go to the documentation of this file.
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% CCCC H H AAA CCCC H H AAA %
7% C H H A A C H H A A %
8% C HHHHH AAAAA C HHHHH AAAAA %
9% C H H A A C H H A A %
10% CCCC H H A A CCCC H H A A %
11% %
12% %
13% Wizard's Toolkit Chacha Cipher Methods %
14% %
15% Software Design %
16% Cristy %
17% March 2009 %
18% %
19% %
20% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% https://imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "wizard/studio.h"
43#include "wizard/chacha.h"
44#include "wizard/exception.h"
46#include "wizard/memory_.h"
47
48/*
49 Typedef declarations.
50*/
52{
53 unsigned int
55 key[16];
56
57 ssize_t
59
60 time_t
62
63 size_t
65};
66
67/*
68 Define declarations.
69*/
70#define ChachaBlocksize 64
71#define PushChachaWord(p) \
72 (((unsigned int) ((p)[0]) << 0) | \
73 ((unsigned int) ((p)[1]) << 8) | \
74 ((unsigned int) ((p)[2]) << 16) | \
75 ((unsigned int) ((p)[3]) << 24))
76
77/*
78%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79% %
80% %
81% %
82% A c q u i r e C h a c h a I n f o %
83% %
84% %
85% %
86%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87%
88% AcquireChachaInfo() allocate the ChachaInfo structure.
89%
90% The format of the AcquireChachaInfo method is:
91%
92% ChachaInfo *AcquireChachaInfo(void)
93%
94*/
96{
98 *chacha_info;
99
100 chacha_info=(ChachaInfo *) AcquireWizardMemory(sizeof(*chacha_info));
101 if (chacha_info == (ChachaInfo *) NULL)
103 (void) memset(chacha_info,0,sizeof(*chacha_info));
104 chacha_info->blocksize=ChachaBlocksize;
105 chacha_info->timestamp=time((time_t *) NULL);
106 chacha_info->signature=WizardSignature;
107 return(chacha_info);
108}
109
110/*
111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112% %
113% %
114% %
115% D e c i p h e r C h a c h a B l o c k %
116% %
117% %
118% %
119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120%
121% DecipherChachaBlock() deciphers a single block of ciphertext to produce a
122% block of plaintext.
123%
124% The format of the DecipherChachaBlock method is:
125%
126% void DecipherChacha(ChachaInfo *chacha_info,
127% const unsigned char *ciphertext,unsigned char *plaintext)
128%
129% A description of each parameter follows:
130%
131% o chacha_info: The cipher context.
132%
133% o ciphertext: The cipher text.
134%
135% o plainttext: The plaint text.
136%
137*/
139 const unsigned char *ciphertext,unsigned char *plaintext)
140{
141 EncipherChachaBlock(chacha_info,ciphertext,plaintext);
142}
143
144/*
145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146% %
147% %
148% %
149% D e s t r o y C h a c h a I n f o %
150% %
151% %
152% %
153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154%
155% DestroyChachaInfo() zeros memory associated with the ChachaInfo structure.
156%
157% The format of the DestroyChachaInfo method is:
158%
159% ChachaInfo *DestroyChachaInfo(ChachaInfo *chacha_info)
160%
161% A description of each parameter follows:
162%
163% o chacha_info: The cipher context.
164%
165*/
167{
169 WizardAssert(CipherDomain,chacha_info != (ChachaInfo *) NULL);
171 chacha_info->signature=(~WizardSignature);
172 chacha_info=(ChachaInfo *) RelinquishWizardMemory(chacha_info);
173 return(chacha_info);
174}
175
176/*
177%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %
178% %
179% %
180% E n c i p h e r C h a c h a B l o c k %
181% %
182% %
183% %
184%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185%
186% EncipherChachaBlock() enciphers a single block of plaintext to produce a
187% block of ciphertext.
188%
189% The format of the EncipherChachaBlock method is:
190%
191% void EncipherChacha(ChachaInfo *chacha_info,
192% const unsigned char *plaintext,unsigned char *ciphertext)
193%
194% A description of each parameter follows:
195%
196% o chacha_info: The cipher context.
197%
198% o plaintext: The plain text.
199%
200% o ciphertext: The cipher text.
201%
202*/
204 const unsigned char *plaintext,unsigned char *ciphertext)
205{
206#define ChachaAdd(v,w) ((unsigned int) ((v)+(w)) & 0xFFFFFFFFU)
207#define ChachaQuarterRound(a,b,c,d) \
208{ \
209 a=ChachaAdd(a,b); d=ChachaRotate((d) ^ (a),16); \
210 c=ChachaAdd(c,d); b=ChachaRotate((b) ^ (c),12); \
211 a=ChachaAdd(a,b); d=ChachaRotate((d) ^ (a), 8); \
212 c=ChachaAdd(c,d); b=ChachaRotate((b) ^ (c), 7); \
213}
214#define ChachaRotate(v,n) \
215 (((unsigned int) ((v) << (n)) & 0xFFFFFFFFU) | ((v) >> (32-(n))))
216#define PopChachaWord(p,v) \
217{ \
218 (p)[0]=((unsigned char) (((v) >> 0) & 0xff)); \
219 (p)[1]=((unsigned char) (((v) >> 8) & 0xff)); \
220 (p)[2]=((unsigned char) (((v) >> 16) & 0xff)); \
221 (p)[3]=((unsigned char) (((v) >> 24) & 0xff)); \
222}
223
224 ssize_t
225 i;
226
227 unsigned int
228 x0,
229 x1,
230 x2,
231 x3,
232 x4,
233 x5,
234 x6,
235 x7,
236 x8,
237 x9,
238 x10,
239 x11,
240 x12,
241 x13,
242 x14,
243 x15;
244
245 /*
246 Encipher one block.
247 */
248 x0=chacha_info->key[0];
249 x1=chacha_info->key[1];
250 x2=chacha_info->key[2];
251 x3=chacha_info->key[3];
252 x4=chacha_info->key[4];
253 x5=chacha_info->key[5];
254 x6=chacha_info->key[6];
255 x7=chacha_info->key[7];
256 x8=chacha_info->key[8];
257 x9=chacha_info->key[9];
258 x10=chacha_info->key[10];
259 x11=chacha_info->key[11];
260 x12=chacha_info->key[12];
261 x13=chacha_info->key[13];
262 x14=chacha_info->key[14];
263 x15=chacha_info->key[15];
264 for (i=20; i > 0; i-=2)
265 {
266 ChachaQuarterRound(x0,x4,x8,x12);
267 ChachaQuarterRound(x1,x5,x9,x13);
268 ChachaQuarterRound(x2,x6,x10,x14);
269 ChachaQuarterRound(x3,x7,x11,x15);
270 ChachaQuarterRound(x0,x5,x10,x15);
271 ChachaQuarterRound(x1,x6,x11,x12);
272 ChachaQuarterRound(x2,x7,x8,x13);
273 ChachaQuarterRound(x3,x4,x9,x14);
274 }
275 x0=ChachaAdd(x0,chacha_info->key[0]);
276 x1=ChachaAdd(x1,chacha_info->key[1]);
277 x2=ChachaAdd(x2,chacha_info->key[2]);
278 x3=ChachaAdd(x3,chacha_info->key[3]);
279 x4=ChachaAdd(x4,chacha_info->key[4]);
280 x5=ChachaAdd(x5,chacha_info->key[5]);
281 x6=ChachaAdd(x6,chacha_info->key[6]);
282 x7=ChachaAdd(x7,chacha_info->key[7]);
283 x8=ChachaAdd(x8,chacha_info->key[8]);
284 x9=ChachaAdd(x9,chacha_info->key[9]);
285 x10=ChachaAdd(x10,chacha_info->key[10]);
286 x11=ChachaAdd(x11,chacha_info->key[11]);
287 x12=ChachaAdd(x12,chacha_info->key[12]);
288 x13=ChachaAdd(x13,chacha_info->key[13]);
289 x14=ChachaAdd(x14,chacha_info->key[14]);
290 x15=ChachaAdd(x15,chacha_info->key[15]);
291 x0^=PushChachaWord(plaintext+0);
292 x1^=PushChachaWord(plaintext+4);
293 x2^=PushChachaWord(plaintext+8);
294 x3^=PushChachaWord(plaintext+12);
295 x4^=PushChachaWord(plaintext+16);
296 x5^=PushChachaWord(plaintext+20);
297 x6^=PushChachaWord(plaintext+24);
298 x7^=PushChachaWord(plaintext+28);
299 x8^=PushChachaWord(plaintext+32);
300 x9^=PushChachaWord(plaintext+36);
301 x10^=PushChachaWord(plaintext+40);
302 x11^=PushChachaWord(plaintext+44);
303 x12^=PushChachaWord(plaintext+48);
304 x13^=PushChachaWord(plaintext+52);
305 x14^=PushChachaWord(plaintext+56);
306 x15^=PushChachaWord(plaintext+60);
307 PopChachaWord(ciphertext+0,x0);
308 PopChachaWord(ciphertext+4,x1);
309 PopChachaWord(ciphertext+8,x2);
310 PopChachaWord(ciphertext+12,x3);
311 PopChachaWord(ciphertext+16,x4);
312 PopChachaWord(ciphertext+20,x5);
313 PopChachaWord(ciphertext+24,x6);
314 PopChachaWord(ciphertext+28,x7);
315 PopChachaWord(ciphertext+32,x8);
316 PopChachaWord(ciphertext+36,x9);
317 PopChachaWord(ciphertext+40,x10);
318 PopChachaWord(ciphertext+44,x11);
319 PopChachaWord(ciphertext+48,x12);
320 PopChachaWord(ciphertext+52,x13);
321 PopChachaWord(ciphertext+56,x14);
322 PopChachaWord(ciphertext+60,x15);
323 /*
324 Reset registers.
325 */
326 x0=0; x1=0; x2=0; x3=0; x4=0; x5=0; x6=0; x7=0;
327 x8=0; x9=0; x10=0; x11=0; x12=0; x13=0; x14=0; x15=0;
328}
329
330/*
331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332% %
333% %
334% %
335% G e t C h a c h a B l o c k s i z e %
336% %
337% %
338% %
339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340%
341% GetChachaBlocksize() returns the Chacha blocksize.
342%
343% The format of the GetChachaBlocksize method is:
344%
345% unsigned int *GetChachaBlocksize(const ChachaInfo *chacha_info)
346%
347% A description of each parameter follows:
348%
349% o chacha_info: The aes info.
350%
351*/
352WizardExport unsigned int GetChachaBlocksize(const ChachaInfo *chacha_info)
353{
355 WizardAssert(CipherDomain,chacha_info != (ChachaInfo *) NULL);
357 return(chacha_info->blocksize);
358}
359
360/*
361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362% %
363% %
364% %
365% S e t C h a c h a K e y %
366% %
367% %
368% %
369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370%
371% SetChachaKey() sets the key for the Chacha cipher. The key length is
372% specified in bits. Valid values are 128, 192, or 256 requiring a key buffer
373% length in bytes of 16, 24, and 32 respectively.
374%
375% The format of the SetChachaKey method is:
376%
377% SetChachaKey(ChachaInfo *chacha_info,const StringInfo *key)
378%
379% A description of each parameter follows:
380%
381% o chacha_info: The cipher context.
382%
383% o key: The key.
384%
385*/
386WizardExport void SetChachaKey(ChachaInfo *chacha_info,const StringInfo *key)
387{
388 const char
389 *constants;
390
391 static const char
392 sigma[17] = "expand 32-byte k",
393 tau[17] = "expand 16-byte k";
394
395 unsigned char
396 *datum;
397
399 WizardAssert(CipherDomain,chacha_info != (ChachaInfo *) NULL);
401 WizardAssert(CipherDomain,key != (StringInfo *) NULL);
402 datum=GetStringInfoDatum(key);
403 if (GetStringInfoLength(key) >= 4)
404 chacha_info->key[4]=PushChachaWord(datum+0);
405 if (GetStringInfoLength(key) >= 8)
406 chacha_info->key[5]=PushChachaWord(datum+4);
407 if (GetStringInfoLength(key) >= 12)
408 chacha_info->key[6]=PushChachaWord(datum+8);
409 if (GetStringInfoLength(key) >= 16)
410 chacha_info->key[7]=PushChachaWord(datum+12);
411 constants=tau;
412 if ((8*GetStringInfoLength(key)) == 256)
413 {
414 datum+=16;
415 constants=sigma;
416 }
417 if (GetStringInfoLength(key) >= 4)
418 chacha_info->key[8]=PushChachaWord(datum+0);
419 if (GetStringInfoLength(key) >= 8)
420 chacha_info->key[9]=PushChachaWord(datum+4);
421 if (GetStringInfoLength(key) >= 12)
422 chacha_info->key[10]=PushChachaWord(datum+8);
423 if (GetStringInfoLength(key) >= 16)
424 chacha_info->key[11]=PushChachaWord(datum+12);
425 chacha_info->key[0]=PushChachaWord(constants+0);
426 chacha_info->key[1]=PushChachaWord(constants+4);
427 chacha_info->key[2]=PushChachaWord(constants+8);
428 chacha_info->key[3]=PushChachaWord(constants+12);
429 chacha_info->key[12]=0; /* we don't use counter in key */
430 chacha_info->key[13]=0; /* we don't use counter in key */
431 chacha_info->key[14]=0;
432 chacha_info->key[15]=0;
433 /*
434 Reset registers.
435 */
436 constants=(const char *) NULL;
437}
438
439/*
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441% %
442% %
443% %
444% S e t C h a c h a N o n c e %
445% %
446% %
447% %
448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449%
450% SetChachaNonce() sets the nonce for the Chacha cipher. The nonce must be
451% at least 8 bytes. The counter can be NULL, if not it must be at least
452% 8 bytes.
453%
454% The format of the SetChachaKey method is:
455%
456% SetChachaKey(ChachaInfo *chacha_info,const unsigned char *nonce,
457% const unsigned char *counter)
458%
459% A description of each parameter follows:
460%
461% o chacha_info: The cipher context.
462%
463% o nonce: The nonce.
464%
465% o counter: The counter.
466%
467*/
469 const unsigned char *nonce,const unsigned char *counter)
470{
471 chacha_info->key[12]=counter == (unsigned char *) NULL ? 0 :
472 PushChachaWord(counter+0);
473 chacha_info->key[13]=counter == (unsigned char *) NULL ? 0 :
474 PushChachaWord(counter+4);
475 chacha_info->key[14]=PushChachaWord(nonce+0);
476 chacha_info->key[15]=PushChachaWord(nonce+4);
477}
#define PopChachaWord(p, v)
WizardExport void EncipherChachaBlock(ChachaInfo *chacha_info, const unsigned char *plaintext, unsigned char *ciphertext)
Definition chacha.c:203
WizardExport ChachaInfo * DestroyChachaInfo(ChachaInfo *chacha_info)
Definition chacha.c:166
#define ChachaQuarterRound(a, b, c, d)
WizardExport void DecipherChachaBlock(ChachaInfo *chacha_info, const unsigned char *ciphertext, unsigned char *plaintext)
Definition chacha.c:138
WizardExport void SetChachaNonce(ChachaInfo *chacha_info, const unsigned char *nonce, const unsigned char *counter)
Definition chacha.c:468
WizardExport void SetChachaKey(ChachaInfo *chacha_info, const StringInfo *key)
Definition chacha.c:386
#define ChachaBlocksize
Definition chacha.c:70
#define ChachaAdd(v, w)
WizardExport unsigned int GetChachaBlocksize(const ChachaInfo *chacha_info)
Definition chacha.c:352
WizardExport ChachaInfo * AcquireChachaInfo(void)
Definition chacha.c:95
#define PushChachaWord(p)
Definition chacha.c:71
#define WizardAssert(domain, predicate)
#define ThrowWizardFatalError(domain, error)
@ CipherDomain
Definition exception.h:34
@ MemoryError
Definition exception.h:49
WizardBooleanType LogWizardEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition log.c:1390
@ TraceEvent
Definition log.h:39
#define GetWizardModule()
Definition log.h:30
WizardExport void * AcquireWizardMemory(const size_t size)
Definition memory.c:586
WizardExport void * RelinquishWizardMemory(void *memory)
Definition memory.c:1039
#define WizardExport
#define WizardSignature
WizardExport size_t GetStringInfoLength(const StringInfo *string_info)
Definition string.c:1280
WizardExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition string.c:1251
unsigned int key[16]
Definition chacha.c:55
size_t signature
Definition chacha.c:64
ssize_t rounds
Definition chacha.c:58
unsigned int blocksize
Definition chacha.c:54
time_t timestamp
Definition chacha.c:61