ltc sync - sosemanuk
Karel Miko
6 years ago
195 | 195 | /* |
196 | 196 | * Key schedule: initialize the key context structure with the provided |
197 | 197 | * secret key. The secret key is an array of 1 to 32 bytes. |
198 | * @param kc The Sosemanuk key context | |
198 | * @param ss The Sosemanuk state | |
199 | 199 | * @param key Key |
200 | * @param key_len Length of key | |
200 | * @param keylen Length of key | |
201 | 201 | * @return CRYPT_OK on success |
202 | 202 | */ |
203 | int sosemanuk_setup(sosemanuk_state *ss, unsigned char *key, unsigned long key_len) | |
203 | int sosemanuk_setup(sosemanuk_state *ss, unsigned char *key, unsigned long keylen) | |
204 | 204 | { |
205 | 205 | /* |
206 | 206 | * This key schedule is actually a truncated Serpent key schedule. |
254 | 254 | ulong32 w0, w1, w2, w3, w4, w5, w6, w7; |
255 | 255 | int i = 0; |
256 | 256 | |
257 | LTC_ARGCHK(ss != NULL); | |
258 | LTC_ARGCHK(key != NULL); | |
259 | ||
260 | /* | |
261 | * Initialize the pointer to 666 as a flag that can be checked | |
262 | * by sosemanuk_crypt() as an indication sosemanuk_setiv() was | |
263 | * not called. (sosemanuk_setiv() will set the pointer to a | |
264 | * more reasonable value.) | |
265 | */ | |
266 | ss->ptr = 666; | |
267 | ||
257 | 268 | /* |
258 | 269 | * The key is copied into the wbuf[] buffer and padded to 256 bits |
259 | 270 | * as described in the Serpent specification. |
260 | 271 | */ |
261 | if (key_len == 0 || key_len > 32) { | |
272 | if (keylen == 0 || keylen > 32) { | |
262 | 273 | fprintf(stderr, "invalid key size: %lu\n", |
263 | (unsigned long)key_len); | |
274 | (unsigned long)keylen); | |
264 | 275 | exit(EXIT_FAILURE); |
265 | 276 | } |
266 | XMEMCPY(wbuf, key, key_len); | |
267 | if (key_len < 32) { | |
268 | wbuf[key_len] = 0x01; | |
269 | if (key_len < 31) | |
270 | XMEMSET(wbuf + key_len + 1, 0, 31 - key_len); | |
277 | XMEMCPY(wbuf, key, keylen); | |
278 | if (keylen < 32) { | |
279 | wbuf[keylen] = 0x01; | |
280 | if (keylen < 31) | |
281 | XMEMSET(wbuf + keylen + 1, 0, 31 - keylen); | |
271 | 282 | } |
272 | 283 | |
273 | 284 | LOAD32L(w0, wbuf); |
325 | 336 | /* |
326 | 337 | * Cipher initialization: the cipher internal state is initialized, using |
327 | 338 | * the provided key context and IV. The IV length is up to 16 bytes. If |
328 | * "iv_len" is 0 (no IV), then the "iv" parameter can be NULL. | |
329 | * @param rc The Sosemanuk run context | |
330 | * @param kc The Sosemanuk key context | |
339 | * "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. | |
340 | * @param ss The Sosemanuk state | |
331 | 341 | * @param iv Initialization vector |
332 | * @param iv_len Length of iv | |
342 | * @param ivlen Length of iv | |
333 | 343 | * @return CRYPT_OK on success |
334 | 344 | */ |
335 | int sosemanuk_setiv(sosemanuk_state *ss, unsigned char *iv, unsigned long iv_len) | |
345 | int sosemanuk_setiv(sosemanuk_state *ss, unsigned char *iv, unsigned long ivlen) | |
336 | 346 | { |
337 | 347 | |
338 | 348 | /* |
370 | 380 | } while (0) |
371 | 381 | |
372 | 382 | ulong32 r0, r1, r2, r3, r4; |
373 | unsigned char ivtmp[16]; | |
374 | ||
375 | if (iv_len >= sizeof ivtmp) { | |
376 | XMEMCPY(ivtmp, iv, sizeof ivtmp); | |
377 | } else { | |
378 | if (iv_len > 0) | |
379 | XMEMCPY(ivtmp, iv, iv_len); | |
380 | XMEMSET(ivtmp + iv_len, 0, (sizeof ivtmp) - iv_len); | |
381 | } | |
383 | unsigned char ivtmp[16] = {0}; | |
384 | ||
385 | LTC_ARGCHK(ss != NULL); | |
386 | LTC_ARGCHK(ivlen >= 0 && ivlen <= 16); | |
387 | LTC_ARGCHK(iv != NULL || ivlen == 0); | |
388 | ||
389 | if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen); | |
382 | 390 | |
383 | 391 | /* |
384 | 392 | * Decode IV into four 32-bit words (little-endian). |
431 | 439 | ss->s01 = r2; |
432 | 440 | ss->s00 = r3; |
433 | 441 | |
434 | ss->ptr = sizeof ss->buf; | |
442 | ss->ptr = sizeof(ss->buf); | |
435 | 443 | |
436 | 444 | #undef KA |
437 | 445 | #undef FSS |
719 | 727 | |
720 | 728 | /* |
721 | 729 | * Combine buffers in1[] and in2[] by XOR, result in out[]. The length |
722 | * is "data_len" (in bytes). Partial overlap of out[] with either in1[] | |
730 | * is "datalen" (in bytes). Partial overlap of out[] with either in1[] | |
723 | 731 | * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2) |
724 | 732 | * is allowed. |
725 | 733 | */ |
726 | 734 | static LTC_INLINE void _xorbuf(const unsigned char *in1, const unsigned char *in2, |
727 | unsigned char *out, unsigned long data_len) | |
735 | unsigned char *out, unsigned long datalen) | |
728 | 736 | { |
729 | while (data_len -- > 0) | |
737 | while (datalen -- > 0) | |
730 | 738 | *out ++ = *in1 ++ ^ *in2 ++; |
731 | 739 | } |
732 | 740 | |
736 | 744 | * buffer, combined by XOR with the stream, and the result is written |
737 | 745 | * in the "out" buffer. "in" and "out" must be either equal, or |
738 | 746 | * reference distinct buffers (no partial overlap is allowed). |
739 | * @param rc The Sosemanuk run context | |
747 | * @param ss The Sosemanuk state | |
740 | 748 | * @param in Data in |
741 | 749 | * @param out Data out |
742 | * @param data_len Length of data | |
750 | * @param datalen Length of data | |
743 | 751 | * @return CRYPT_OK on success |
744 | 752 | */ |
745 | 753 | int sosemanuk_crypt(sosemanuk_state *ss, |
746 | const unsigned char *in, unsigned long data_len, unsigned char *out) | |
754 | const unsigned char *in, unsigned long datalen, unsigned char *out) | |
747 | 755 | { |
748 | if (ss->ptr < (sizeof ss->buf)) { | |
749 | unsigned long rlen = (sizeof ss->buf) - ss->ptr; | |
750 | ||
751 | if (rlen > data_len) | |
752 | rlen = data_len; | |
756 | LTC_ARGCHK(ss != NULL); | |
757 | LTC_ARGCHK(in != NULL); | |
758 | LTC_ARGCHK(out != NULL); | |
759 | LTC_ARGCHK(ss->ptr != 666); /* check whether sosemanuk_setiv was called */ | |
760 | ||
761 | if (ss->ptr < (sizeof(ss->buf))) { | |
762 | unsigned long rlen = (sizeof(ss->buf)) - ss->ptr; | |
763 | ||
764 | if (rlen > datalen) | |
765 | rlen = datalen; | |
753 | 766 | _xorbuf(ss->buf + ss->ptr, in, out, rlen); |
754 | 767 | in += rlen; |
755 | 768 | out += rlen; |
756 | data_len -= rlen; | |
769 | datalen -= rlen; | |
757 | 770 | ss->ptr += rlen; |
758 | 771 | } |
759 | while (data_len > 0) { | |
772 | while (datalen > 0) { | |
760 | 773 | _sosemanuk_internal(ss); |
761 | if (data_len >= sizeof ss->buf) { | |
762 | _xorbuf(ss->buf, in, out, sizeof ss->buf); | |
763 | in += sizeof ss->buf; | |
764 | out += sizeof ss->buf; | |
765 | data_len -= sizeof ss->buf; | |
774 | if (datalen >= sizeof(ss->buf)) { | |
775 | _xorbuf(ss->buf, in, out, sizeof(ss->buf)); | |
776 | in += sizeof(ss->buf); | |
777 | out += sizeof(ss->buf); | |
778 | datalen -= sizeof(ss->buf); | |
766 | 779 | } else { |
767 | _xorbuf(ss->buf, in, out, data_len); | |
768 | ss->ptr = data_len; | |
769 | data_len = 0; | |
780 | _xorbuf(ss->buf, in, out, datalen); | |
781 | ss->ptr = datalen; | |
782 | datalen = 0; | |
770 | 783 | } |
771 | 784 | } |
772 | 785 | return CRYPT_OK; |
776 | 789 | /* |
777 | 790 | * Cipher operation, as a PRNG: the provided output buffer is filled with |
778 | 791 | * pseudo-random bytes as output from the stream cipher. |
779 | * @param rc The Sosemanuk run context | |
792 | * @param ss The Sosemanuk state | |
780 | 793 | * @param out Data out |
781 | * @param out_len Length of output | |
794 | * @param outlen Length of output | |
782 | 795 | * @return CRYPT_OK on success |
783 | 796 | */ |
784 | int sosemanuk_keystream(sosemanuk_state *ss, unsigned char *out, unsigned long out_len) | |
797 | int sosemanuk_keystream(sosemanuk_state *ss, unsigned char *out, unsigned long outlen) | |
785 | 798 | { |
786 | if (ss->ptr < (sizeof ss->buf)) { | |
787 | unsigned long rlen = (sizeof ss->buf) - ss->ptr; | |
788 | ||
789 | if (rlen > out_len) | |
790 | rlen = out_len; | |
791 | XMEMCPY(out, ss->buf + ss->ptr, rlen); | |
792 | out += rlen; | |
793 | out_len -= rlen; | |
794 | ss->ptr += rlen; | |
795 | } | |
796 | while (out_len > 0) { | |
797 | _sosemanuk_internal(ss); | |
798 | if (out_len >= sizeof ss->buf) { | |
799 | XMEMCPY(out, ss->buf, sizeof ss->buf); | |
800 | out += sizeof ss->buf; | |
801 | out_len -= sizeof ss->buf; | |
802 | } else { | |
803 | XMEMCPY(out, ss->buf, out_len); | |
804 | ss->ptr = out_len; | |
805 | out_len = 0; | |
806 | } | |
807 | } | |
808 | return CRYPT_OK; | |
799 | if (outlen == 0) return CRYPT_OK; /* nothing to do */ | |
800 | LTC_ARGCHK(out != NULL); | |
801 | XMEMSET(out, 0, outlen); | |
802 | return sosemanuk_crypt(ss, out, outlen, out); | |
809 | 803 | } |
810 | 804 | |
811 | 805 |