1 /* low-crypto.c --- Shishi crypto wrappers around generic crypto.
2  * Copyright (C) 2002-2013 Simon Josefsson
3  *
4  * This file is part of Shishi.
5  *
6  * Shishi is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Shishi is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Shishi; if not, see http://www.gnu.org/licenses or write
18  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19  * Floor, Boston, MA 02110-1301, USA
20  *
21  */
22 
23 #include "internal.h"
24 #include "gc.h"
25 #include "arcfour.h"
26 #include <gcrypt.h>
27 #include "crc.h"
28 #include "low-crypto.h"
29 
30 int
_shishi_crypto_init(Shishi * handle)31 _shishi_crypto_init (Shishi * handle)
32 {
33   int rc = gc_init ();
34 
35   if (rc != GC_OK)
36     return SHISHI_CRYPTO_INTERNAL_ERROR;
37 
38   return SHISHI_OK;
39 }
40 
41 void
_shishi_quick_random(void)42 _shishi_quick_random (void)
43 {
44   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
45 }
46 
47 /**
48  * shishi_randomize:
49  * @handle: shishi handle as allocated by shishi_init().
50  * @strong: 0 iff operation should not block, non-0 for very strong randomness.
51  * @data: output array to be filled with random data.
52  * @datalen: size of output array.
53  *
54  * Store cryptographically random data of given size in the provided
55  * buffer.
56  *
57  * Return value: Returns %SHISHI_OK iff successful.
58  **/
59 int
shishi_randomize(Shishi * handle,int strong,void * data,size_t datalen)60 shishi_randomize (Shishi * handle, int strong, void *data, size_t datalen)
61 {
62   Gc_rc rc;
63 
64   if (strong)
65     rc = gc_random (data, datalen);
66   else
67     rc = gc_pseudo_random (data, datalen);
68 
69   if (rc != GC_OK)
70     return SHISHI_FILE_ERROR;
71 
72   return SHISHI_OK;
73 }
74 
75 /**
76  * shishi_crc:
77  * @handle: shishi handle as allocated by shishi_init().
78  * @in: input character array of data to checksum.
79  * @inlen: length of input character array of data to checksum.
80  * @out: newly allocated character array with checksum of data.
81  *
82  * Compute checksum of data using CRC32 modified according to RFC
83  * 1510.  The @out buffer must be deallocated by the caller.
84  *
85  * The modifications compared to standard CRC32 is that no initial and
86  * final XOR is performed, and that the output is returned in
87  * LSB-first order.
88  *
89  * Return value: Returns SHISHI_OK iff successful.
90  **/
91 int
shishi_crc(Shishi * handle,const char * in,size_t inlen,char * out[4])92 shishi_crc (Shishi * handle, const char *in, size_t inlen, char *out[4])
93 {
94   uint32_t crc = crc32_update_no_xor (0, in, inlen);
95 
96   *out = xmalloc (4);
97   (*out)[0] = crc & 0xFF;
98   (*out)[1] = (crc >> 8) & 0xFF;
99   (*out)[2] = (crc >> 16) & 0xFF;
100   (*out)[3] = (crc >> 24) & 0xFF;
101 
102   return SHISHI_OK;
103 }
104 
105 /**
106  * shishi_md4:
107  * @handle: shishi handle as allocated by shishi_init().
108  * @in: input character array of data to hash.
109  * @inlen: length of input character array of data to hash.
110  * @out: newly allocated character array with hash of data.
111  *
112  * Compute hash of data using MD4.  The @out buffer must be
113  * deallocated by the caller.
114  *
115  * Return value: Returns SHISHI_OK iff successful.
116  **/
117 int
shishi_md4(Shishi * handle,const char * in,size_t inlen,char * out[16])118 shishi_md4 (Shishi * handle, const char *in, size_t inlen, char *out[16])
119 {
120   Gc_rc rc;
121 
122   *out = xmalloc (GC_MD4_DIGEST_SIZE);
123   rc = gc_md4 (in, inlen, *out);
124   if (rc != GC_OK)
125     return SHISHI_CRYPTO_INTERNAL_ERROR;
126 
127   return SHISHI_OK;
128 }
129 
130 /**
131  * shishi_md5:
132  * @handle: shishi handle as allocated by shishi_init().
133  * @in: input character array of data to hash.
134  * @inlen: length of input character array of data to hash.
135  * @out: newly allocated character array with hash of data.
136  *
137  * Compute hash of data using MD5.  The @out buffer must be
138  * deallocated by the caller.
139  *
140  * Return value: Returns SHISHI_OK iff successful.
141  **/
142 int
shishi_md5(Shishi * handle,const char * in,size_t inlen,char * out[16])143 shishi_md5 (Shishi * handle, const char *in, size_t inlen, char *out[16])
144 {
145   Gc_rc rc;
146 
147   *out = xmalloc (GC_MD5_DIGEST_SIZE);
148   rc = gc_md5 (in, inlen, *out);
149   if (rc != GC_OK)
150     return SHISHI_CRYPTO_INTERNAL_ERROR;
151 
152   return SHISHI_OK;
153 }
154 
155 /**
156  * shishi_hmac_md5:
157  * @handle: shishi handle as allocated by shishi_init().
158  * @key: input character array with key to use.
159  * @keylen: length of input character array with key to use.
160  * @in: input character array of data to hash.
161  * @inlen: length of input character array of data to hash.
162  * @outhash: newly allocated character array with keyed hash of data.
163  *
164  * Compute keyed checksum of data using HMAC-MD5.  The @outhash buffer
165  * must be deallocated by the caller.
166  *
167  * Return value: Returns SHISHI_OK iff successful.
168  **/
169 int
shishi_hmac_md5(Shishi * handle,const char * key,size_t keylen,const char * in,size_t inlen,char * outhash[16])170 shishi_hmac_md5 (Shishi * handle,
171 		 const char *key, size_t keylen,
172 		 const char *in, size_t inlen, char *outhash[16])
173 {
174   Gc_rc rc;
175 
176   *outhash = xmalloc (GC_MD5_DIGEST_SIZE);
177   rc = gc_hmac_md5 (key, keylen, in, inlen, *outhash);
178   if (rc != GC_OK)
179     return SHISHI_CRYPTO_INTERNAL_ERROR;
180 
181   return SHISHI_OK;
182 }
183 
184 /**
185  * shishi_hmac_sha1:
186  * @handle: shishi handle as allocated by shishi_init().
187  * @key: input character array with key to use.
188  * @keylen: length of input character array with key to use.
189  * @in: input character array of data to hash.
190  * @inlen: length of input character array of data to hash.
191  * @outhash: newly allocated character array with keyed hash of data.
192  *
193  * Compute keyed checksum of data using HMAC-SHA1.  The @outhash
194  * buffer must be deallocated by the caller.
195  *
196  * Return value: Returns SHISHI_OK iff successful.
197  **/
198 int
shishi_hmac_sha1(Shishi * handle,const char * key,size_t keylen,const char * in,size_t inlen,char * outhash[20])199 shishi_hmac_sha1 (Shishi * handle,
200 		  const char *key, size_t keylen,
201 		  const char *in, size_t inlen, char *outhash[20])
202 {
203   Gc_rc rc;
204 
205   *outhash = xmalloc (GC_SHA1_DIGEST_SIZE);
206   rc = gc_hmac_sha1 (key, keylen, in, inlen, *outhash);
207   if (rc != GC_OK)
208     return SHISHI_CRYPTO_INTERNAL_ERROR;
209 
210   return SHISHI_OK;
211 }
212 
213 /**
214  * shishi_des_cbc_mac:
215  * @handle: shishi handle as allocated by shishi_init().
216  * @key: input character array with key to use.
217  * @iv: input character array with initialization vector to use, can be NULL.
218  * @in: input character array of data to hash.
219  * @inlen: length of input character array of data to hash.
220  * @out: newly allocated character array with keyed hash of data.
221  *
222  * Computed keyed checksum of data using DES-CBC-MAC.  The @out buffer
223  * must be deallocated by the caller.
224  *
225  * Return value: Returns SHISHI_OK iff successful.
226  **/
227 int
shishi_des_cbc_mac(Shishi * handle,const char key[8],const char iv[8],const char * in,size_t inlen,char * out[8])228 shishi_des_cbc_mac (Shishi * handle,
229 		    const char key[8],
230 		    const char iv[8],
231 		    const char *in, size_t inlen, char *out[8])
232 {
233   gcry_cipher_hd_t ch;
234   gpg_error_t err;
235   int res = SHISHI_CRYPTO_INTERNAL_ERROR;
236 
237   err = gcry_cipher_open (&ch, GCRY_CIPHER_DES,
238 			  GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC);
239   if (err != GPG_ERR_NO_ERROR)
240     {
241       shishi_error_printf (handle, "DES-CBC-MAC not available in libgcrypt");
242       return SHISHI_CRYPTO_INTERNAL_ERROR;
243     }
244 
245   err = gcry_cipher_setkey (ch, key, 8);
246   if (err != GPG_ERR_NO_ERROR)
247     {
248       shishi_error_printf (handle, "DES setkey failed");
249       shishi_error_set (handle, gpg_strerror (err));
250       goto done;
251     }
252 
253   err = gcry_cipher_setiv (ch, iv, 8);
254   if (err != GPG_ERR_NO_ERROR)
255     {
256       shishi_error_printf (handle, "DES setiv failed");
257       shishi_error_set (handle, gpg_strerror (err));
258       goto done;
259     }
260 
261   *out = xmalloc (8);
262 
263   err = gcry_cipher_encrypt (ch, *out, 8, in, inlen);
264   if (err != GPG_ERR_NO_ERROR)
265     {
266       shishi_error_printf (handle, "DES encrypt failed");
267       shishi_error_set (handle, gpg_strerror (err));
268       goto done;
269     }
270 
271   res = SHISHI_OK;
272 
273 done:
274   gcry_cipher_close (ch);
275   return res;
276 }
277 
278 static int
libgcrypt_dencrypt(Shishi * handle,int algo,int flags,int mode,int decryptp,const char * key,size_t keylen,const char * iv,char ** ivout,const char * in,size_t inlen,char ** out)279 libgcrypt_dencrypt (Shishi * handle, int algo, int flags, int mode,
280 		    int decryptp,
281 		    const char *key, size_t keylen,
282 		    const char *iv,
283 		    char **ivout, const char *in, size_t inlen, char **out)
284 {
285   size_t ivlen = gcry_cipher_get_algo_blklen (algo);
286   gcry_cipher_hd_t ch;
287   gpg_error_t err;
288 
289   err = gcry_cipher_open (&ch, algo, mode, flags);
290   if (err != GPG_ERR_NO_ERROR)
291     {
292       shishi_error_printf (handle, "Libgcrypt cipher open failed");
293       shishi_error_set (handle, gpg_strerror (err));
294       return SHISHI_CRYPTO_INTERNAL_ERROR;
295     }
296 
297   err = gcry_cipher_setkey (ch, key, keylen);
298   if (err != GPG_ERR_NO_ERROR)
299     {
300       shishi_error_printf (handle, "Libgcrypt setkey failed");
301       shishi_error_set (handle, gpg_strerror (err));
302       return SHISHI_CRYPTO_INTERNAL_ERROR;
303     }
304 
305   err = gcry_cipher_setiv (ch, iv, ivlen);
306   if (err != GPG_ERR_NO_ERROR)
307     {
308       shishi_error_printf (handle, "Libgcrypt setiv failed");
309       shishi_error_set (handle, gpg_strerror (err));
310       return SHISHI_CRYPTO_INTERNAL_ERROR;
311     }
312 
313   *out = xmalloc (inlen);
314 
315   if (decryptp)
316     err = gcry_cipher_decrypt (ch, (unsigned char *) *out, inlen,
317 			       (const unsigned char *) in, inlen);
318   else
319     err = gcry_cipher_encrypt (ch, (unsigned char *) *out, inlen,
320 			       (const unsigned char *) in, inlen);
321   if (err != GPG_ERR_NO_ERROR)
322     {
323       shishi_error_printf (handle, "Libgcrypt ciphering failed");
324       shishi_error_set (handle, gpg_strerror (err));
325       return SHISHI_CRYPTO_INTERNAL_ERROR;
326     }
327 
328   if (ivout)
329     {
330       size_t ivdiff, ivpos = 0;
331 
332       *ivout = xmalloc (ivlen);
333 
334       if (flags & GCRY_CIPHER_CBC_CTS)
335 	{
336 	  /* XXX what is the output iv for CBC-CTS mode?
337 	     but is this value useful at all for that mode anyway?
338 	     Mostly it is DES apps that want the updated iv, so this is ok. */
339 
340 	  if (inlen % ivlen)
341 	    ivdiff = ivlen + inlen % ivlen;
342 	  else
343 	    ivdiff = ivlen + ivlen;
344 
345 	  if (inlen >= ivdiff)
346 	    ivpos = inlen - ivdiff;
347 	}
348       else
349 	ivpos = inlen - ivlen;
350 
351       if (decryptp)
352 	memcpy (*ivout, in + ivpos, inlen >= ivlen ? ivlen : inlen);
353       else
354 	memcpy (*ivout, *out + ivpos, inlen >= ivlen ? ivlen : inlen);
355     }
356 
357   gcry_cipher_close (ch);
358 
359   return SHISHI_OK;
360 }
361 
362 /**
363  * shishi_arcfour:
364  * @handle: shishi handle as allocated by shishi_init().
365  * @decryptp: 0 to indicate encryption, non-0 to indicate decryption.
366  * @key: input character array with key to use.
367  * @keylen: length of input key array.
368  * @iv: input character array with initialization vector to use, or NULL.
369  * @ivout: output character array with updated initialization vector, or NULL.
370  * @in: input character array of data to encrypt/decrypt.
371  * @inlen: length of input character array of data to encrypt/decrypt.
372  * @out: newly allocated character array with encrypted/decrypted data.
373  *
374  * Encrypt or decrypt data (depending on @decryptp) using ARCFOUR.
375  * The @out buffer must be deallocated by the caller.
376  *
377  * The "initialization vector" used here is the concatenation of the
378  * sbox and i and j, and is thus always of size 256 + 1 + 1.  This is
379  * a slight abuse of terminology, and assumes you know what you are
380  * doing.  Don't use it if you can avoid to.
381  *
382  * Return value: Returns SHISHI_OK iff successful.
383  **/
384 int
shishi_arcfour(Shishi * handle,int decryptp,const char * key,size_t keylen,const char iv[258],char * ivout[258],const char * in,size_t inlen,char ** out)385 shishi_arcfour (Shishi * handle, int decryptp,
386 		const char *key, size_t keylen,
387 		const char iv[258], char *ivout[258],
388 		const char *in, size_t inlen, char **out)
389 {
390   arcfour_context ctx;
391 
392   *out = xmalloc (inlen);
393 
394   if (iv)
395     memcpy (&ctx, iv, sizeof (ctx));
396   else
397     arcfour_setkey (&ctx, key, keylen);
398 
399   arcfour_stream (&ctx, in, *out, inlen);
400 
401   if (ivout)
402     {
403       *ivout = xmalloc (sizeof (ctx));
404       memcpy (*ivout, &ctx, sizeof (ctx));
405     }
406 
407   return SHISHI_OK;
408 }
409 
410 /**
411  * shishi_des:
412  * @handle: shishi handle as allocated by shishi_init().
413  * @decryptp: 0 to indicate encryption, non-0 to indicate decryption.
414  * @key: input character array with key to use.
415  * @iv: input character array with initialization vector to use, or NULL.
416  * @ivout: output character array with updated initialization vector, or NULL.
417  * @in: input character array of data to encrypt/decrypt.
418  * @inlen: length of input character array of data to encrypt/decrypt.
419  * @out: newly allocated character array with encrypted/decrypted data.
420  *
421  * Encrypt or decrypt data (depending on @decryptp) using DES in CBC
422  * mode.  The @out buffer must be deallocated by the caller.
423  *
424  * Return value: Returns SHISHI_OK iff successful.
425  **/
426 int
shishi_des(Shishi * handle,int decryptp,const char key[8],const char iv[8],char * ivout[8],const char * in,size_t inlen,char ** out)427 shishi_des (Shishi * handle, int decryptp,
428 	    const char key[8],
429 	    const char iv[8],
430 	    char *ivout[8], const char *in, size_t inlen, char **out)
431 {
432   return libgcrypt_dencrypt (handle, GCRY_CIPHER_DES, 0, GCRY_CIPHER_MODE_CBC,
433 			     decryptp, key, 8, iv, ivout, in, inlen, out);
434 }
435 
436 /**
437  * shishi_3des:
438  * @handle: shishi handle as allocated by shishi_init().
439  * @decryptp: 0 to indicate encryption, non-0 to indicate decryption.
440  * @key: input character array with key to use.
441  * @iv: input character array with initialization vector to use, or NULL.
442  * @ivout: output character array with updated initialization vector, or NULL.
443  * @in: input character array of data to encrypt/decrypt.
444  * @inlen: length of input character array of data to encrypt/decrypt.
445  * @out: newly allocated character array with encrypted/decrypted data.
446  *
447  * Encrypt or decrypt data (depending on @decryptp) using 3DES in CBC
448  * mode.  The @out buffer must be deallocated by the caller.
449  *
450  * Return value: Returns SHISHI_OK iff successful.
451  **/
452 int
shishi_3des(Shishi * handle,int decryptp,const char key[8],const char iv[8],char * ivout[8],const char * in,size_t inlen,char ** out)453 shishi_3des (Shishi * handle, int decryptp,
454 	     const char key[8],
455 	     const char iv[8],
456 	     char *ivout[8], const char *in, size_t inlen, char **out)
457 {
458   return libgcrypt_dencrypt (handle, GCRY_CIPHER_3DES, 0,
459 			     GCRY_CIPHER_MODE_CBC, decryptp, key, 24, iv,
460 			     ivout, in, inlen, out);
461 }
462 
463 /**
464  * shishi_aes_cts:
465  * @handle: shishi handle as allocated by shishi_init().
466  * @decryptp: 0 to indicate encryption, non-0 to indicate decryption.
467  * @key: input character array with key to use.
468  * @keylen: length of input character array with key to use.
469  * @iv: input character array with initialization vector to use, or NULL.
470  * @ivout: output character array with updated initialization vector, or NULL.
471  * @in: input character array of data to encrypt/decrypt.
472  * @inlen: length of input character array of data to encrypt/decrypt.
473  * @out: newly allocated character array with encrypted/decrypted data.
474  *
475  * Encrypt or decrypt data (depending on @decryptp) using AES in
476  * CBC-CTS mode.  The length of the key, @keylen, decide if AES 128 or
477  * AES 256 should be used.  The @out buffer must be deallocated by the
478  * caller.
479  *
480  * Return value: Returns SHISHI_OK iff successful.
481  **/
482 int
shishi_aes_cts(Shishi * handle,int decryptp,const char * key,size_t keylen,const char iv[16],char * ivout[16],const char * in,size_t inlen,char ** out)483 shishi_aes_cts (Shishi * handle, int decryptp,
484 		const char *key, size_t keylen,
485 		const char iv[16],
486 		char *ivout[16], const char *in, size_t inlen, char **out)
487 {
488   return libgcrypt_dencrypt (handle, GCRY_CIPHER_AES, GCRY_CIPHER_CBC_CTS,
489 			     GCRY_CIPHER_MODE_CBC, decryptp,
490 			     key, keylen, iv, ivout, in, inlen, out);
491 }
492 
493 /**
494  * shishi_pbkdf2_sha1:
495  * @handle: shishi handle as allocated by shishi_init().
496  * @P: input password, an octet string
497  * @Plen: length of password, an octet string
498  * @S: input salt, an octet string
499  * @Slen: length of salt, an octet string
500  * @c: iteration count, a positive integer
501  * @dkLen: intended length in octets of the derived key, a positive integer,
502  *   at most (2^32 - 1) * hLen.  The DK array must have room for this many
503  *   characters.
504  * @DK: output derived key, a dkLen-octet string
505  *
506  * Derive key using the PBKDF2 defined in PKCS5.  PBKDF2 applies a
507  * pseudorandom function to derive keys. The length of the derived key
508  * is essentially unbounded. (However, the maximum effective search
509  * space for the derived key may be limited by the structure of the
510  * underlying pseudorandom function, which is this function is always
511  * SHA1.)
512  *
513  * Return value: Returns SHISHI_OK iff successful.
514  **/
515 int
shishi_pbkdf2_sha1(Shishi * handle,const char * P,size_t Plen,const char * S,size_t Slen,unsigned int c,unsigned int dkLen,char * DK)516 shishi_pbkdf2_sha1 (Shishi * handle,
517 		    const char *P, size_t Plen,
518 		    const char *S, size_t Slen,
519 		    unsigned int c, unsigned int dkLen, char *DK)
520 {
521   Gc_rc rc;
522 
523   rc = gc_pbkdf2_sha1 (P, Plen, S, Slen, c, DK, dkLen);
524 
525   if (rc == GC_PKCS5_INVALID_ITERATION_COUNT)
526     return SHISHI_PKCS5_INVALID_ITERATION_COUNT;
527 
528   if (rc == GC_PKCS5_INVALID_DERIVED_KEY_LENGTH)
529     return SHISHI_PKCS5_INVALID_DERIVED_KEY_LENGTH;
530 
531   if (rc == GC_PKCS5_DERIVED_KEY_TOO_LONG)
532     return SHISHI_PKCS5_DERIVED_KEY_TOO_LONG;
533 
534   if (rc != GC_OK)
535     return SHISHI_CRYPTO_INTERNAL_ERROR;
536 
537   return SHISHI_OK;
538 }
539