The unified diff between revisions [1626dca9..] and [a1c3f430..] is displayed below. It can also be downloaded as a raw diff.
#
#
# delete "PLAN"
#
# delete "base64.c"
#
# delete "crypt.out"
#
# delete "crypt.pdf"
#
# delete "gf.c"
#
# delete "keyring.c"
#
# delete "mycrypt_gf.h"
#
# delete "rsa.c"
#
# delete "rsa_sys.c"
#
# delete "strings.c"
#
# delete "tommath.h"
#
# add_dir "demos/test"
#
# add_dir "doc"
#
# add_file "base64_decode.c"
# content [49ccbccfc3b994abf9539af29b18d0d37991e060]
#
# add_file "base64_encode.c"
# content [41306437f35d6fd1a1462446b9b9967237a4572d]
#
# add_file "cbc_getiv.c"
# content [e988ddd3049ba757b3fd6597cf7668edfb00f5a6]
#
# add_file "cbc_setiv.c"
# content [8e48c5f46e2363cd36e0d27081f7d52c0ea571df]
#
# add_file "cfb_getiv.c"
# content [59ac5e237c81e1f436a0b8da54bcc5c353506fe1]
#
# add_file "cfb_setiv.c"
# content [639e29970bb27da0715e6c70eb528e3b6f6aa749]
#
# add_file "ctr_getiv.c"
# content [6bd784631074f758a426149338a9c276034bc3e1]
#
# add_file "ctr_setiv.c"
# content [6ba792cb56a6d9298a143de79da714c2c99b82e5]
#
# add_file "demos/test/base64_test.c"
# content [8563403c95aa7f401d28e079a11ae1546f53a819]
#
# add_file "demos/test/cipher_hash_test.c"
# content [5583bea1f573708f68ac52da3c4852e9708b94ed]
#
# add_file "demos/test/dh_tests.c"
# content [db5836adc0a960ff208b529cc1a8060ddf3840b8]
#
# add_file "demos/test/dsa_test.c"
# content [dda7a8784e843636c1b201a616989e7deadda832]
#
# add_file "demos/test/ecc_test.c"
# content [c6f856ccd26a648520e74dfc3671db2423887755]
#
# add_file "demos/test/mac_test.c"
# content [b146fe51848f5a83eca8b0d3019a18e51e35eed1]
#
# add_file "demos/test/makefile"
# content [41cb74e27182085077426a8a65ce689d74631997]
#
# add_file "demos/test/makefile.icc"
# content [ba1e3cae1c73187489c4366a45bc0333b0138be3]
#
# add_file "demos/test/makefile.msvc"
# content [e1dce5e5ec45d9d7d54f6de85c86bb9077e214a4]
#
# add_file "demos/test/modes_test.c"
# content [82f5d5a22220c23604ef85c0b6365a9dd044b165]
#
# add_file "demos/test/pkcs_1_test.c"
# content [5cd09f8b0ebd98bb507bbd83b1ea22a31e4bfa9b]
#
# add_file "demos/test/rsa_test.c"
# content [5c282302d927e2683f17ff312cf50d7afbfd9080]
#
# add_file "demos/test/store_test.c"
# content [d202711443c1aee0e06d8fcc691883ea5f8e56c5]
#
# add_file "demos/test/test.c"
# content [671f2b2af594fcf024cf2c7819d3bb11b520372b]
#
# add_file "demos/test/test.h"
# content [ca8227f354a804ca3d084fae803b0993c37dbf5d]
#
# add_file "doc/crypt.pdf"
# content [f4d9846f37129b03cdf8969976365a05bd4be09b]
#
# add_file "error_to_string.c"
# content [4b53223659cd11cfedabf2dbd1ac1f00064ec812]
#
# add_file "ltc_tommath.h"
# content [c8e202d5b2b69feb8a255872514685eccf82bb03]
#
# add_file "modes_test.c"
# content [5fb32a2a1cdc4311654b80d027a10dbdcf09fc4b]
#
# add_file "mpi_to_ltc_error.c"
# content [7d237900c806bdaf1b45494089d37020aa4051f9]
#
# add_file "ofb_getiv.c"
# content [78815a65ad0934db29c875cf19333887ad1d46e5]
#
# add_file "ofb_setiv.c"
# content [45017eac234d24e2f2f6c766f36ec6d7ff72788a]
#
# add_file "pkcs_1_v15_es_decode.c"
# content [21f620c947db684ab3bc11e051edc1d0176086f4]
#
# add_file "pkcs_1_v15_es_encode.c"
# content [fb6d3ddfe5810de3c92b46edb0f4c8a7b6de615b]
#
# add_file "pkcs_1_v15_sa_decode.c"
# content [4f6aeaa76927807827ad5a472b8e84d600f9f6cd]
#
# add_file "pkcs_1_v15_sa_encode.c"
# content [0f05185ad6c209d813573788e5cf5057e9dbaf66]
#
# add_file "rsa_decrypt_key.c"
# content [471c35e6305e3e3a7819d08525526b0019248723]
#
# add_file "rsa_encrypt_key.c"
# content [1ca9226d54ce36a9e700000145db98a22b3753d5]
#
# add_file "rsa_export.c"
# content [520f23951ac1fd1e28ab14a9283ef84abacc8baa]
#
# add_file "rsa_import.c"
# content [4a7e1456f13ac5313a999164c2f7e41022c3419b]
#
# add_file "rsa_sign_hash.c"
# content [d3856ae248e093d7f73f48dee96911f2293cd4a5]
#
# add_file "rsa_verify_hash.c"
# content [a1667bf6fa35453ae0b69bfec574ab3c39525935]
#
# add_file "tim_exptmod.c"
# content [80dfac51cb0dd33e4d80702187313fc7d96d52d4]
#
# patch "aes.c"
# from [decb06209890d202bdaa2b2095344580bb9d4b13]
# to [34c70069a1c05c3e8d6e42f1ef10495b271f425d]
#
# patch "aes_tab.c"
# from [026d6575ce571ca3ca33e828c9c7c75dc787c696]
# to [8d84d7ccee23e01c4a8f876735478b5a44d4bd42]
#
# patch "cbc_decrypt.c"
# from [f6a28de38f7e35337bc38c2f5a81e60cdc104a05]
# to [290fb8f65b1037f8479d118dd94340458eeaed8d]
#
# patch "changes"
# from [1dfeb3f2aedcb7f984297fb7d4a7afdbff1cb674]
# to [b68f47aa1ca092c730b59b38f794c822f473902e]
#
# patch "crypt.c"
# from [c1c89e3e4d520f3674362686f4b2eb652350c71f]
# to [14fd6a0ac48eea8e092891cc828a900b55682689]
#
# patch "crypt.tex"
# from [8e63225b182ba100c6698dcea5381fb0debcb46e]
# to [f230cd06ff9351b7e4a36fa9a6932a55cedc295f]
#
# patch "crypt_hash_descriptor.c"
# from [d0386cb2ec1370c57309cb15e08e95c5ca627cd5]
# to [b5a017b295b4284cddcd27e504148811b52b3405]
#
# patch "demos/small.c"
# from [1a4e2dca6b16d1474e29005fa8451ddfae81abf8]
# to [440bca5f72e64be156dbc6485f6068ce0fe8b794]
#
# patch "demos/test.c"
# from [8548c615d06874b5dae9c3959db9855c499863e0]
# to [8cc348c95e2631175ebf374edfd3df934607b5f8]
#
# patch "ecb_decrypt.c"
# from [53780e706a225c2f685332a70fb98a20a462c625]
# to [92321c1426f8be007eac0df4caf7635cbb5e216f]
#
# patch "makefile"
# from [b4e997bd6c027d59e2a60ce4b079a9256967bb4b]
# to [f34bcc5442faad26bb98cd87a2eafd6c788f5184]
#
# patch "makefile.cygwin_dll"
# from [803e293fbcdeadc6bdb7229739e61b83791e31cc]
# to [4eee01a79b76b8ba00eccd58b686305d6ff84462]
#
# patch "makefile.icc"
# from [a82a0d6536f7f69b62b0a15d5ba385ccb5ca2879]
# to [e951e45a38738fb5a3d61ac43bc039140d34c535]
#
# patch "makefile.msvc"
# from [b820f04a1e6db4ebeead72049de0b0d93f93e238]
# to [79b8467715506130a3f3cb20525399f225e623b1]
#
# patch "md2.c"
# from [b4db9406ea825037a46546994b7f9fb0e5bd21e1]
# to [446a9d5577967f794c594cfb724dcf1dc48f94fb]
#
# patch "md4.c"
# from [850599f3a17573e4a2e9c3c69122df74b1d8515f]
# to [834f4fe24b63861b8787897b033d4f124c064dd4]
#
# patch "md5.c"
# from [9f6e0c2df3f95e20f91c5c346d6ce3110b160591]
# to [146b63b358a6d9e087ff5921e29b5a530ec2e7cd]
#
# patch "mpi.c"
# from [b7d2e380f9a57fad2340798f43f3fc652df5067f]
# to [95d17e02a09052c7d53ac093066d971f828fe9d7]
#
# patch "mycrypt.h"
# from [47a3216a12b8ce2f4d6efeb0f78b5d39a823ee64]
# to [67d2c66396a3d3b332f8ebfb3610ee752c55474e]
#
# patch "mycrypt_cipher.h"
# from [9deee5e42419a480952beac21c104be76423b6c7]
# to [c3ce8966f910ff29ec719b9af7d87b70686a02c4]
#
# patch "mycrypt_custom.h"
# from [aa735b140b9925a32fc521e2ba92b4f0a3079110]
# to [71c0e7f5d117e5dbbddd77ba1e75d962f49af33f]
#
# patch "mycrypt_hash.h"
# from [c0e65e241aad97d124741afcc296c4c823034081]
# to [93c98acbf5e1bf8a08ee1e9934bfa55881986c47]
#
# patch "mycrypt_pk.h"
# from [b9e347a708e04c332933960fd95ac17f4a20568d]
# to [ec5fb7007b02c76f82ff0f24fc340d95396cdefa]
#
# patch "mycrypt_pkcs.h"
# from [315b6018cad585c9c9d5a854bd25e2a8d0cf915a]
# to [9f28361cb5f5126bc309575ca33b0e30e884ff2e]
#
# patch "ocb_decrypt.c"
# from [9092f4c0199562e9bf3e9f28774ceb9038373c1c]
# to [d36abea76b375107933ed6e71564de088a203682]
#
# patch "pkcs_1_oaep_decode.c"
# from [729397dd6a0a98faff0b8df3b3db64f7355084ee]
# to [ff3eb43d282de73d129242a35ad6ee9fbff0209c]
#
# patch "pkcs_1_oaep_encode.c"
# from [eb6e0a6299b6464d9f26286cd00d84671adfc87b]
# to [4e2fad693071f6eab8883542033a88320709b883]
#
# patch "pkcs_1_pss_decode.c"
# from [5165a09c5d765df08c24aa67068bfc20b07d0d3a]
# to [4098b3b99c9f32ac78ca7aa7d9fe4154e14dd23f]
#
# patch "pkcs_1_pss_encode.c"
# from [b2f328321d233df002192b465777bba6dd6ae3e7]
# to [a0c15b111517e97a0f55182ad9f8ccf9a6167c4e]
#
# patch "rand_prime.c"
# from [ec5e7efda34d965eae1cbb0a52473db479da8e35]
# to [716723552a2ccc6a70d253135151d4595825359a]
#
# patch "rmd128.c"
# from [7b52ad77825ff94107226edb710d014068a2d3f7]
# to [749732011d84577bed3c9366ea090b9b6a5c2441]
#
# patch "rmd160.c"
# from [a0f49ecdfe69fc098a299235f93520507cabcd5c]
# to [b8595a8ed7d693ee5c60c5e8e71f722eb6c41092]
#
# patch "rsa_exptmod.c"
# from [6361b239258c3ee1a169a04e01c147080dade30e]
# to [c23f2543a33b6fe7b8d0bab375336352c85ee739]
#
# patch "rsa_make_key.c"
# from [8c7c819a278a233cdb9dec1f7eac36a593955059]
# to [59612917f688ba173a370b6e6cb5274c151047dd]
#
# patch "sha1.c"
# from [c219f8d01e686c965739cf4c1157d6faf63568c5]
# to [82ab6899fadd59a69f080fcedea62a128c60acc7]
#
# patch "sha224.c"
# from [1dbca996c51893963ecfa5a76ce3a0a00e0cf664]
# to [7a2466729d8dbe51079d1ea89b42a1e422e0ab98]
#
# patch "sha256.c"
# from [76ba884bf17db0300ef57bd04970b814bec0c634]
# to [2087aaa8b96b7f63cb7025e6abb3f812aaf354bd]
#
# patch "sha384.c"
# from [1c06293daaa40114f78aa9b2aa8f38a2b271866e]
# to [4f1a92e2a188be6eb754d19b718a2450a921e2c6]
#
# patch "sha512.c"
# from [f679021c238038f2e8c8b8a15416563d6a2833bc]
# to [a656eaab1f2dd2fbbeb63b88967cad0c11fa1f7d]
#
# patch "tiger.c"
# from [893ab0b0444497740dc3458fdc9532c3897e98f8]
# to [7250776761a9c629f1a2ff94764f0ba57f830726]
#
# patch "whirl.c"
# from [1b15f087805d4d22edfce19f9edf987d87b1081f]
# to [4036d1c6ad3f1421be81c3e928483f40ae3334c8]
#
# patch "yarrow.c"
# from [438250d987fc8762d3329b2364d8b737d49de06a]
# to [443c387d2a917a521ba0a203e674bc6781155296]
#
============================================================
--- base64_decode.c 49ccbccfc3b994abf9539af29b18d0d37991e060
+++ base64_decode.c 49ccbccfc3b994abf9539af29b18d0d37991e060
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+/* compliant base64 code donated by Wayne Scott (wscott@bitmover.com) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+static const unsigned char map[256] = {
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
+255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
+255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255 };
+
+int base64_decode(const unsigned char *in, unsigned long len,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long t, x, y, z;
+ unsigned char c;
+ int g;
+
+ _ARGCHK(in != NULL);
+ _ARGCHK(out != NULL);
+ _ARGCHK(outlen != NULL);
+
+ g = 3;
+ for (x = y = z = t = 0; x < len; x++) {
+ c = map[in[x]&0xFF];
+ if (c == 255) continue;
+ if (c == 254) { c = 0; g--; }
+ t = (t<<6)|c;
+ if (++y == 4) {
+ if (z + g > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[z++] = (unsigned char)((t>>16)&255);
+ if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
+ if (g > 2) out[z++] = (unsigned char)(t&255);
+ y = t = 0;
+ }
+ }
+ if (y != 0) {
+ return CRYPT_INVALID_PACKET;
+ }
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- base64_encode.c 41306437f35d6fd1a1462446b9b9967237a4572d
+++ base64_encode.c 41306437f35d6fd1a1462446b9b9967237a4572d
@@ -0,0 +1,63 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+/* compliant base64 code donated by Wayne Scott (wscott@bitmover.com) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+static const char *codes =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int base64_encode(const unsigned char *in, unsigned long len,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long i, len2, leven;
+ unsigned char *p;
+
+ _ARGCHK(in != NULL);
+ _ARGCHK(out != NULL);
+ _ARGCHK(outlen != NULL);
+
+ /* valid output size ? */
+ len2 = 4 * ((len + 2) / 3);
+ if (*outlen < len2 + 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ p = out;
+ leven = 3*(len / 3);
+ for (i = 0; i < leven; i += 3) {
+ *p++ = codes[(in[0] >> 2) & 0x3F];
+ *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
+ *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
+ *p++ = codes[in[2] & 0x3F];
+ in += 3;
+ }
+ /* Pad it if necessary... */
+ if (i < len) {
+ unsigned a = in[0];
+ unsigned b = (i+1 < len) ? in[1] : 0;
+
+ *p++ = codes[(a >> 2) & 0x3F];
+ *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
+ *p++ = (i+1 < len) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
+ *p++ = '=';
+ }
+
+ /* append a NULL byte */
+ *p = '\0';
+
+ /* return ok */
+ *outlen = p - out;
+ return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- cbc_getiv.c e988ddd3049ba757b3fd6597cf7668edfb00f5a6
+++ cbc_getiv.c e988ddd3049ba757b3fd6597cf7668edfb00f5a6
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CBC
+
+int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc)
+{
+ _ARGCHK(IV != NULL);
+ _ARGCHK(len != NULL);
+ _ARGCHK(cbc != NULL);
+ if ((unsigned long)cbc->blocklen > *len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ memcpy(IV, cbc->IV, cbc->blocklen);
+ *len = cbc->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
============================================================
--- cbc_setiv.c 8e48c5f46e2363cd36e0d27081f7d52c0ea571df
+++ cbc_setiv.c 8e48c5f46e2363cd36e0d27081f7d52c0ea571df
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CBC
+
+int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc)
+{
+ _ARGCHK(IV != NULL);
+ _ARGCHK(cbc != NULL);
+ if (len != (unsigned long)cbc->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+ memcpy(cbc->IV, IV, len);
+ return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- cfb_getiv.c 59ac5e237c81e1f436a0b8da54bcc5c353506fe1
+++ cfb_getiv.c 59ac5e237c81e1f436a0b8da54bcc5c353506fe1
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CFB
+
+int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb)
+{
+ _ARGCHK(IV != NULL);
+ _ARGCHK(len != NULL);
+ _ARGCHK(cfb != NULL);
+ if ((unsigned long)cfb->blocklen > *len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ memcpy(IV, cfb->IV, cfb->blocklen);
+ *len = cfb->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
============================================================
--- cfb_setiv.c 639e29970bb27da0715e6c70eb528e3b6f6aa749
+++ cfb_setiv.c 639e29970bb27da0715e6c70eb528e3b6f6aa749
@@ -0,0 +1,39 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CFB
+
+int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb)
+{
+ int err;
+
+ _ARGCHK(IV != NULL);
+ _ARGCHK(cfb != NULL);
+
+ if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len != (unsigned long)cfb->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* force next block */
+ cfb->padlen = 0;
+ cipher_descriptor[cfb->cipher].ecb_encrypt(IV, cfb->IV, &cfb->key);
+
+ return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- ctr_getiv.c 6bd784631074f758a426149338a9c276034bc3e1
+++ ctr_getiv.c 6bd784631074f758a426149338a9c276034bc3e1
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CTR
+
+int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr)
+{
+ _ARGCHK(IV != NULL);
+ _ARGCHK(len != NULL);
+ _ARGCHK(ctr != NULL);
+ if ((unsigned long)ctr->blocklen > *len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ memcpy(IV, ctr->ctr, ctr->blocklen);
+ *len = ctr->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
============================================================
--- ctr_setiv.c 6ba792cb56a6d9298a143de79da714c2c99b82e5
+++ ctr_setiv.c 6ba792cb56a6d9298a143de79da714c2c99b82e5
@@ -0,0 +1,43 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CTR
+
+int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr)
+{
+ int err;
+
+ _ARGCHK(IV != NULL);
+ _ARGCHK(ctr != NULL);
+
+ /* bad param? */
+ if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len != (unsigned long)ctr->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* set IV */
+ memcpy(ctr->ctr, IV, len);
+
+ /* force next block */
+ ctr->padlen = 0;
+ cipher_descriptor[ctr->cipher].ecb_encrypt(IV, ctr->pad, &ctr->key);
+
+ return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- demos/test/base64_test.c 8563403c95aa7f401d28e079a11ae1546f53a819
+++ demos/test/base64_test.c 8563403c95aa7f401d28e079a11ae1546f53a819
@@ -0,0 +1,20 @@
+#include "test.h"
+
+int base64_test(void)
+{
+ unsigned char in[64], out[256], tmp[64];
+ unsigned long x, l1, l2;
+
+ for (x = 0; x < 64; x++) {
+ yarrow_read(in, x, &test_yarrow);
+ l1 = sizeof(out);
+ DO(base64_encode(in, x, out, &l1));
+ l2 = sizeof(tmp);
+ DO(base64_decode(out, l1, tmp, &l2));
+ if (l2 != x || memcmp(tmp, in, x)) {
+ printf("base64 failed %lu %lu %lu", x, l1, l2);
+ return 1;
+ }
+ }
+ return 0;
+}
============================================================
--- demos/test/cipher_hash_test.c 5583bea1f573708f68ac52da3c4852e9708b94ed
+++ demos/test/cipher_hash_test.c 5583bea1f573708f68ac52da3c4852e9708b94ed
@@ -0,0 +1,20 @@
+/* test the ciphers and hashes using their built-in self-tests */
+
+#include "test.h"
+
+int cipher_hash_test(void)
+{
+ int x;
+
+ /* test ciphers */
+ for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+ DO(cipher_descriptor[x].test());
+ }
+
+ /* test hashes */
+ for (x = 0; hash_descriptor[x].name != NULL; x++) {
+ DO(hash_descriptor[x].test());
+ }
+
+ return 0;
+}
============================================================
--- demos/test/dh_tests.c db5836adc0a960ff208b529cc1a8060ddf3840b8
+++ demos/test/dh_tests.c db5836adc0a960ff208b529cc1a8060ddf3840b8
@@ -0,0 +1,87 @@
+#include "test.h"
+
+int dh_tests (void)
+{
+ unsigned char buf[3][4096];
+ unsigned long x, y, z;
+ int stat, stat2;
+ dh_key usera, userb;
+
+ DO(dh_test());
+
+ /* make up two keys */
+ DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &usera));
+ DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &userb));
+
+ /* make the shared secret */
+ x = 4096;
+ DO(dh_shared_secret (&usera, &userb, buf[0], &x));
+
+ y = 4096;
+ DO(dh_shared_secret (&userb, &usera, buf[1], &y));
+ if (y != x) {
+ printf ("DH Shared keys are not same size.\n");
+ return 1;
+ }
+ if (memcmp (buf[0], buf[1], x)) {
+ printf ("DH Shared keys not same contents.\n");
+ return 1;
+ }
+
+ /* now export userb */
+ y = 4096;
+ DO(dh_export (buf[1], &y, PK_PUBLIC, &userb));
+ dh_free (&userb);
+
+ /* import and make the shared secret again */
+ DO(dh_import (buf[1], y, &userb));
+ z = 4096;
+ DO(dh_shared_secret (&usera, &userb, buf[2], &z));
+
+ if (z != x) {
+ printf ("failed. Size don't match?\n");
+ return 1;
+ }
+ if (memcmp (buf[0], buf[2], x)) {
+ printf ("Failed. Content didn't match.\n");
+ return 1;
+ }
+ dh_free (&usera);
+ dh_free (&userb);
+
+/* test encrypt_key */
+ dh_make_key (&test_yarrow, find_prng ("yarrow"), 128, &usera);
+ for (x = 0; x < 16; x++) {
+ buf[0][x] = x;
+ }
+ y = sizeof (buf[1]);
+ DO(dh_encrypt_key (buf[0], 16, buf[1], &y, &test_yarrow, find_prng ("yarrow"), find_hash ("md5"), &usera));
+ zeromem (buf[0], sizeof (buf[0]));
+ x = sizeof (buf[0]);
+ DO(dh_decrypt_key (buf[1], y, buf[0], &x, &usera));
+ if (x != 16) {
+ printf ("Failed (length)\n");
+ return 1;
+ }
+ for (x = 0; x < 16; x++)
+ if (buf[0][x] != x) {
+ printf ("Failed (contents)\n");
+ return 1;
+ }
+
+/* test sign_hash */
+ for (x = 0; x < 16; x++) {
+ buf[0][x] = x;
+ }
+ x = sizeof (buf[1]);
+ DO(dh_sign_hash (buf[0], 16, buf[1], &x, &test_yarrow , find_prng ("yarrow"), &usera));
+ DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
+ buf[0][0] ^= 1;
+ DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
+ if (!(stat == 1 && stat2 == 0)) {
+ printf("dh_sign/verify_hash %d %d", stat, stat2);
+ return 1;
+ }
+ dh_free (&usera);
+ return 0;
+}
============================================================
--- demos/test/dsa_test.c dda7a8784e843636c1b201a616989e7deadda832
+++ demos/test/dsa_test.c dda7a8784e843636c1b201a616989e7deadda832
@@ -0,0 +1,51 @@
+#include "test.h"
+
+int dsa_test(void)
+{
+ unsigned char msg[16], out[1024], out2[1024];
+ unsigned long x, y;
+ int err, stat1, stat2;
+ dsa_key key, key2;
+
+ /* make a random key */
+ DO(dsa_make_key(&test_yarrow, find_prng("yarrow"), 20, 128, &key));
+
+ /* verify it */
+ DO(dsa_verify_key(&key, &stat1));
+ if (stat1 == 0) { printf("dsa_verify_key "); return 1; }
+
+ /* sign the message */
+ x = sizeof(out);
+ DO(dsa_sign_hash(msg, sizeof(msg), out, &x, &test_yarrow, find_prng("yarrow"), &key));
+
+ /* verify it once */
+ DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key));
+
+ /* Modify and verify again */
+ msg[0] ^= 1;
+ DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key));
+ msg[0] ^= 1;
+ if (!(stat1 == 1 && stat2 == 0)) { printf("dsa_verify %d %d", stat1, stat2); return 1; }
+
+ /* test exporting it */
+ x = sizeof(out2);
+ DO(dsa_export(out2, &x, PK_PRIVATE, &key));
+ DO(dsa_import(out2, x, &key2));
+
+ /* verify a signature with it */
+ DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2));
+ if (stat1 == 0) { printf("dsa_verify (import private) %d ", stat1); return 1; }
+ dsa_free(&key2);
+
+ /* export as public now */
+ x = sizeof(out2);
+ DO(dsa_export(out2, &x, PK_PUBLIC, &key));
+ DO(dsa_import(out2, x, &key2));
+ /* verify a signature with it */
+ DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2));
+ if (stat1 == 0) { printf("dsa_verify (import public) %d ", stat1); return 1; }
+ dsa_free(&key2);
+ dsa_free(&key);
+
+ return 0;
+}
============================================================
--- demos/test/ecc_test.c c6f856ccd26a648520e74dfc3671db2423887755
+++ demos/test/ecc_test.c c6f856ccd26a648520e74dfc3671db2423887755
@@ -0,0 +1,89 @@
+#include "test.h"
+
+int ecc_tests (void)
+{
+ unsigned char buf[4][4096];
+ unsigned long x, y, z;
+ int stat, stat2;
+ ecc_key usera, userb;
+
+ DO(ecc_test ());
+
+ /* make up two keys */
+ DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 24, &usera));
+ DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 24, &userb));
+
+ /* make the shared secret */
+ x = 4096;
+ DO(ecc_shared_secret (&usera, &userb, buf[0], &x));
+
+ y = 4096;
+ DO(ecc_shared_secret (&userb, &usera, buf[1], &y));
+
+ if (y != x) {
+ printf ("ecc Shared keys are not same size.");
+ return 1;
+ }
+
+ if (memcmp (buf[0], buf[1], x)) {
+ printf ("ecc Shared keys not same contents.");
+ return 1;
+ }
+
+ /* now export userb */
+ y = 4096;
+ DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb));
+ ecc_free (&userb);
+
+ /* import and make the shared secret again */
+ DO(ecc_import (buf[1], y, &userb));
+
+ z = 4096;
+ DO(ecc_shared_secret (&usera, &userb, buf[2], &z));
+
+ if (z != x) {
+ printf ("failed. Size don't match?");
+ return 1;
+ }
+ if (memcmp (buf[0], buf[2], x)) {
+ printf ("Failed. Content didn't match.");
+ return 1;
+ }
+ ecc_free (&usera);
+ ecc_free (&userb);
+
+/* test encrypt_key */
+ ecc_make_key (&test_yarrow, find_prng ("yarrow"), 20, &usera);
+ for (x = 0; x < 32; x++) {
+ buf[0][x] = x;
+ }
+ y = sizeof (buf[1]);
+ DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &test_yarrow, find_prng ("yarrow"), find_hash ("sha256"), &usera));
+ zeromem (buf[0], sizeof (buf[0]));
+ x = sizeof (buf[0]);
+ DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &usera));
+ if (x != 32) {
+ printf ("Failed (length)");
+ return 1;
+ }
+ for (x = 0; x < 32; x++)
+ if (buf[0][x] != x) {
+ printf ("Failed (contents)");
+ return 1;
+ }
+/* test sign_hash */
+ for (x = 0; x < 16; x++) {
+ buf[0][x] = x;
+ }
+ x = sizeof (buf[1]);
+ DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &test_yarrow, find_prng ("yarrow"), &usera));
+ DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
+ buf[0][0] ^= 1;
+ DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
+ if (!(stat == 1 && stat2 == 0)) {
+ printf("ecc_verify_hash failed");
+ return 1;
+ }
+ ecc_free (&usera);
+ return 0;
+}
============================================================
--- demos/test/mac_test.c b146fe51848f5a83eca8b0d3019a18e51e35eed1
+++ demos/test/mac_test.c b146fe51848f5a83eca8b0d3019a18e51e35eed1
@@ -0,0 +1,12 @@
+/* test pmac/omac/hmac */
+#include "test.h"
+
+int mac_test(void)
+{
+ DO(hmac_test());
+ DO(pmac_test());
+ DO(omac_test());
+ DO(eax_test());
+ DO(ocb_test());
+ return 0;
+}
============================================================
--- demos/test/makefile 41cb74e27182085077426a8a65ce689d74631997
+++ demos/test/makefile 41cb74e27182085077426a8a65ce689d74631997
@@ -0,0 +1,13 @@
+# make test harness, it is good.
+CFLAGS += -Wall -W -Os -I../../ -I./
+
+default: test
+
+OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o
+
+test: $(OBJECTS)
+ $(CC) $(OBJECTS) -ltomcrypt -o test
+
+clean:
+ rm -f test *.o *.obj *.exe *~
============================================================
--- demos/test/makefile.icc ba1e3cae1c73187489c4366a45bc0333b0138be3
+++ demos/test/makefile.icc ba1e3cae1c73187489c4366a45bc0333b0138be3
@@ -0,0 +1,14 @@
+# make test harness, it is good.
+CFLAGS += -O3 -xN -ip -I../../ -I./
+CC=icc
+
+default: test
+
+OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o
+
+test: $(OBJECTS)
+ $(CC) $(OBJECTS) -ltomcrypt -o test
+
+clean:
+ rm -f test *.o *~
============================================================
--- demos/test/makefile.msvc e1dce5e5ec45d9d7d54f6de85c86bb9077e214a4
+++ demos/test/makefile.msvc e1dce5e5ec45d9d7d54f6de85c86bb9077e214a4
@@ -0,0 +1,14 @@
+# make test harness, it is good.
+CFLAGS = $(CFLAGS) /W3 /Ox -I../../ -I./
+
+default: test.exe
+
+OBJECTS = test.obj cipher_hash_test.obj mac_test.obj modes_test.obj \
+pkcs_1_test.obj store_test.obj rsa_test.obj ecc_test.obj dsa_test.c dh_tests.obj
+
+
+test.exe: $(OBJECTS)
+ cl $(OBJECTS) tomcrypt.lib advapi32.lib
+
+clean:
+ rm -f test.exe *.obj *~
============================================================
--- demos/test/modes_test.c 82f5d5a22220c23604ef85c0b6365a9dd044b165
+++ demos/test/modes_test.c 82f5d5a22220c23604ef85c0b6365a9dd044b165
@@ -0,0 +1,112 @@
+/* test CFB/OFB/CBC modes */
+#include "test.h"
+
+int modes_test(void)
+{
+ unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16];
+ int x, cipher_idx;
+ symmetric_CBC cbc;
+ symmetric_CFB cfb;
+ symmetric_OFB ofb;
+ symmetric_CTR ctr;
+ unsigned long l;
+
+ /* make a random pt, key and iv */
+ yarrow_read(pt, 64, &test_yarrow);
+ yarrow_read(key, 16, &test_yarrow);
+ yarrow_read(iv, 16, &test_yarrow);
+
+ /* get idx of AES handy */
+ cipher_idx = find_cipher("aes");
+ if (cipher_idx == -1) {
+ printf("test requires AES");
+ return 1;
+ }
+
+ /* test CBC mode */
+ /* encode the block */
+ DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+ l = sizeof(iv2);
+ DO(cbc_getiv(iv2, &l, &cbc));
+ if (l != 16 || memcmp(iv2, iv, 16)) {
+ printf("cbc_getiv failed");
+ return 1;
+ }
+ for (x = 0; x < 4; x++) {
+ DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc));
+ }
+
+ /* decode the block */
+ DO(cbc_setiv(iv2, l, &cbc));
+ zeromem(tmp, sizeof(tmp));
+ for (x = 0; x < 4; x++) {
+ DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc));
+ }
+ if (memcmp(tmp, pt, 64) != 0) {
+ printf("CBC failed");
+ return 1;
+ }
+
+ /* test CFB mode */
+ /* encode the block */
+ DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb));
+ l = sizeof(iv2);
+ DO(cfb_getiv(iv2, &l, &cfb));
+ /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */
+ if (l != 16) {
+ printf("cfb_getiv failed");
+ return 1;
+ }
+ DO(cfb_encrypt(pt, ct, 64, &cfb));
+
+ /* decode the block */
+ DO(cfb_setiv(iv, l, &cfb));
+ zeromem(tmp, sizeof(tmp));
+ DO(cfb_decrypt(ct, tmp, 64, &cfb));
+ if (memcmp(tmp, pt, 64) != 0) {
+ printf("CFB failed");
+ return 1;
+ }
+
+ /* test OFB mode */
+ /* encode the block */
+ DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb));
+ l = sizeof(iv2);
+ DO(ofb_getiv(iv2, &l, &ofb));
+ if (l != 16 || memcmp(iv2, iv, 16)) {
+ printf("ofb_getiv failed");
+ return 1;
+ }
+ DO(ofb_encrypt(pt, ct, 64, &ofb));
+
+ /* decode the block */
+ DO(ofb_setiv(iv2, l, &ofb));
+ zeromem(tmp, sizeof(tmp));
+ DO(ofb_decrypt(ct, tmp, 64, &ofb));
+ if (memcmp(tmp, pt, 64) != 0) {
+ printf("OFB failed");
+ return 1;
+ }
+
+ /* test CTR mode */
+ /* encode the block */
+ DO(ctr_start(cipher_idx, iv, key, 16, 0, &ctr));
+ l = sizeof(iv2);
+ DO(ctr_getiv(iv2, &l, &ctr));
+ if (l != 16 || memcmp(iv2, iv, 16)) {
+ printf("ctr_getiv failed");
+ return 1;
+ }
+ DO(ctr_encrypt(pt, ct, 64, &ctr));
+
+ /* decode the block */
+ DO(ctr_setiv(iv2, l, &ctr));
+ zeromem(tmp, sizeof(tmp));
+ DO(ctr_decrypt(ct, tmp, 64, &ctr));
+ if (memcmp(tmp, pt, 64) != 0) {
+ printf("CTR failed");
+ return 1;
+ }
+
+ return 0;
+}
============================================================
--- demos/test/pkcs_1_test.c 5cd09f8b0ebd98bb507bbd83b1ea22a31e4bfa9b
+++ demos/test/pkcs_1_test.c 5cd09f8b0ebd98bb507bbd83b1ea22a31e4bfa9b
@@ -0,0 +1,103 @@
+#include "test.h"
+
+int pkcs_1_test(void)
+{
+ unsigned char buf[3][128];
+ int res1, res2, res3, prng_idx, hash_idx;
+ unsigned long x, y, l1, l2, l3, i1, i2, lparamlen, saltlen, modlen;
+ static const unsigned char lparam[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
+
+ /* get hash/prng */
+ hash_idx = find_hash("sha1");
+ prng_idx = find_prng("yarrow");
+
+ if (hash_idx == -1 || prng_idx == -1) {
+ printf("pkcs_1 tests require sha1/yarrow");
+ return 1;
+ }
+
+ /* do many tests */
+ for (x = 0; x < 10000; x++) {
+ zeromem(buf, sizeof(buf));
+
+ /* make a dummy message (of random length) */
+ l3 = (rand() & 31) + 8;
+ for (y = 0; y < l3; y++) buf[0][y] = rand() & 255;
+
+ /* random modulus len (v1.5 must be multiple of 8 though arbitrary sizes seem to work) */
+ modlen = 800 + 8 * (abs(rand()) % 28);
+
+ /* PKCS v1.5 testing (encryption) */
+ l1 = sizeof(buf[1]);
+ DO(pkcs_1_v15_es_encode(buf[0], l3, modlen, &test_yarrow, prng_idx, buf[1], &l1));
+ DO(pkcs_1_v15_es_decode(buf[1], l1, modlen, buf[2], l3, &res1));
+ if (res1 != 1 || memcmp(buf[0], buf[2], l3)) {
+ printf("pkcs v1.5 encrypt failed %d, %lu, %lu ", res1, l1, l3);
+ return 1;
+ }
+
+ /* PKCS v1.5 testing (signatures) */
+ l1 = sizeof(buf[1]);
+ DO(pkcs_1_v15_sa_encode(buf[0], l3, hash_idx, modlen, buf[1], &l1));
+ DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res1));
+ buf[0][i1 = abs(rand()) % l3] ^= 1;
+ DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res2));
+ buf[0][i1] ^= 1;
+ buf[1][i2 = abs(rand()) % l1] ^= 1;
+ DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res3));
+
+ if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
+ printf("pkcs v1.5 sign failed %d %d %d ", res1, res2, res3);
+ return 1;
+ }
+
+ /* pick a random lparam len [0..16] */
+ lparamlen = abs(rand()) % 17;
+
+ /* pick a random saltlen 0..16 */
+ saltlen = abs(rand()) % 17;
+
+ /* PKCS #1 v2.0 supports modlens not multiple of 8 */
+ modlen = 800 + (abs(rand()) % 224);
+
+ /* encode it */
+ l1 = sizeof(buf[1]);
+ DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &test_yarrow, prng_idx, hash_idx, buf[1], &l1));
+
+ /* decode it */
+ l2 = sizeof(buf[2]);
+ DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1));
+
+ if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) {
+ printf("Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen);
+ printf("ORIGINAL:\n");
+ for (x = 0; x < l3; x++) {
+ printf("%02x ", buf[0][x]);
+ }
+ printf("\nRESULT:\n");
+ for (x = 0; x < l2; x++) {
+ printf("%02x ", buf[2][x]);
+ }
+ printf("\n\n");
+ return 1;
+ }
+
+ /* test PSS */
+ l1 = sizeof(buf[1]);
+ DO(pkcs_1_pss_encode(buf[0], l3, saltlen, &test_yarrow, prng_idx, hash_idx, modlen, buf[1], &l1));
+ DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res1));
+
+ buf[0][i1 = abs(rand()) % l3] ^= 1;
+ DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res2));
+
+ buf[0][i1] ^= 1;
+ buf[1][i2 = abs(rand()) % l1] ^= 1;
+ DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res3));
+
+ if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
+ printf("PSS failed: %d, %d, %d, %lu, %lu\n", res1, res2, res3, l3, saltlen);
+ return 1;
+ }
+ }
+ return 0;
+}
============================================================
--- demos/test/rsa_test.c 5c282302d927e2683f17ff312cf50d7afbfd9080
+++ demos/test/rsa_test.c 5c282302d927e2683f17ff312cf50d7afbfd9080
@@ -0,0 +1,91 @@
+#include "test.h"
+
+int rsa_test(void)
+{
+ unsigned char in[1024], out[1024], tmp[1024];
+ rsa_key key;
+ int hash_idx, prng_idx, stat, stat2;
+ unsigned long len, len2;
+ static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 };
+
+ hash_idx = find_hash("sha1");
+ prng_idx = find_prng("yarrow");
+ if (hash_idx == -1 || prng_idx == -1) {
+ printf("rsa_test requires SHA1 and yarrow");
+ return 1;
+ }
+
+ /* make a random key/msg */
+ yarrow_read(in, 20, &test_yarrow);
+
+ /* make a random key */
+ DO(rsa_make_key(&test_yarrow, prng_idx, 1024/8, 65537, &key));
+
+ /* encrypt the key (without lparam) */
+ len = sizeof(out);
+ len2 = sizeof(tmp);
+ DO(rsa_encrypt_key(in, 20, out, &len, NULL, 0, &test_yarrow, prng_idx, hash_idx, &key));
+ /* change a byte */
+ out[0] ^= 1;
+ DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+ /* change a byte back */
+ out[0] ^= 1;
+ DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, &test_yarrow, prng_idx, hash_idx, &stat, &key));
+ if (!(stat == 1 && stat2 == 0)) {
+ printf("rsa_decrypt_key failed");
+ return 1;
+ }
+ if (len2 != 20 || memcmp(tmp, in, 20)) {
+ printf("rsa_decrypt_key mismatch len %lu", len2);
+ return 1;
+ }
+
+ /* encrypt the key (with lparam) */
+ len = sizeof(out);
+ len2 = sizeof(tmp);
+ DO(rsa_encrypt_key(in, 20, out, &len, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &key));
+ /* change a byte */
+ out[0] ^= 1;
+ DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+ /* change a byte back */
+ out[0] ^= 1;
+ DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &stat, &key));
+ if (!(stat == 1 && stat2 == 0)) {
+ printf("rsa_decrypt_key failed");
+ return 1;
+ }
+ if (len2 != 20 || memcmp(tmp, in, 20)) {
+ printf("rsa_decrypt_key mismatch len %lu", len2);
+ return 1;
+ }
+
+ /* sign a message (unsalted, lower cholestorol and Atkins approved) now */
+ len = sizeof(out);
+ DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 0, &key));
+ DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &key));
+ /* change a byte */
+ in[0] ^= 1;
+ DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &key));
+
+ if (!(stat == 1 && stat2 == 0)) {
+ printf("rsa_verify_hash (unsalted) failed, %d, %d", stat, stat2);
+ return 1;
+ }
+
+ /* sign a message (salted) now */
+ len = sizeof(out);
+ DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 8, &key));
+ DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat, &key));
+ /* change a byte */
+ in[0] ^= 1;
+ DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat2, &key));
+
+ if (!(stat == 1 && stat2 == 0)) {
+ printf("rsa_verify_hash (salted) failed, %d, %d", stat, stat2);
+ return 1;
+ }
+
+ /* free the key and return */
+ rsa_free(&key);
+ return 0;
+}
============================================================
--- demos/test/store_test.c d202711443c1aee0e06d8fcc691883ea5f8e56c5
+++ demos/test/store_test.c d202711443c1aee0e06d8fcc691883ea5f8e56c5
@@ -0,0 +1,43 @@
+#include "test.h"
+
+int store_test(void)
+{
+ unsigned char buf[8];
+ unsigned long L;
+ ulong64 LL;
+
+ L = 0x12345678UL;
+ STORE32L (L, &buf[0]);
+ L = 0;
+ LOAD32L (L, &buf[0]);
+ if (L != 0x12345678UL) {
+ printf ("LOAD/STORE32 Little don't work");
+ return 1;
+ }
+ LL = CONST64 (0x01020304050607);
+ STORE64L (LL, &buf[0]);
+ LL = 0;
+ LOAD64L (LL, &buf[0])
+ if (LL != CONST64 (0x01020304050607)) {
+ printf ("LOAD/STORE64 Little don't work");
+ return 1;
+ }
+
+ L = 0x12345678UL;
+ STORE32H (L, &buf[0]);
+ L = 0;
+ LOAD32H (L, &buf[0]);
+ if (L != 0x12345678UL) {
+ printf ("LOAD/STORE32 High don't work, %08lx", L);
+ return 1;
+ }
+ LL = CONST64 (0x01020304050607);
+ STORE64H (LL, &buf[0]);
+ LL = 0;
+ LOAD64H (LL, &buf[0])
+ if (LL != CONST64 (0x01020304050607)) {
+ printf ("LOAD/STORE64 High don't work");
+ return 1;
+ }
+ return 0;
+}
============================================================
--- demos/test/test.c 671f2b2af594fcf024cf2c7819d3bb11b520372b
+++ demos/test/test.c 671f2b2af594fcf024cf2c7819d3bb11b520372b
@@ -0,0 +1,177 @@
+#include "test.h"
+
+test_entry tests[26];
+
+test_entry test_list[26] = {
+
+/* test name provides requires entry */
+{"store_test", "a", "", store_test },
+{"cipher_hash_test", "b", "a", cipher_hash_test },
+{"modes_test", "c", "b", modes_test },
+{"mac_test", "d", "c", mac_test },
+{"pkcs_1_test", "e", "b", pkcs_1_test },
+{"rsa_test", "f", "e", rsa_test },
+{"ecc_test", "g", "a", ecc_tests },
+{"dsa_test", "h", "a", dsa_test },
+{"dh_test", "i", "a", dh_tests },
+
+{NULL, NULL, NULL, NULL}
+};
+
+prng_state test_yarrow;
+static int current_test;
+
+void run_cmd(int res, int line, char *file, char *cmd)
+{
+ if (res != CRYPT_OK) {
+ fprintf(stderr, "[%s]: %s (%d)\n%s:%d:%s\n", tests[current_test].name, error_to_string(res), res, file, line, cmd);
+ exit(EXIT_FAILURE);
+ }
+}
+
+void register_algs(void)
+{
+#ifdef RIJNDAEL
+ register_cipher (&aes_desc);
+#endif
+#ifdef BLOWFISH
+ register_cipher (&blowfish_desc);
+#endif
+#ifdef XTEA
+ register_cipher (&xtea_desc);
+#endif
+#ifdef RC5
+ register_cipher (&rc5_desc);
+#endif
+#ifdef RC6
+ register_cipher (&rc6_desc);
+#endif
+#ifdef SAFERP
+ register_cipher (&saferp_desc);
+#endif
+#ifdef TWOFISH
+ register_cipher (&twofish_desc);
+#endif
+#ifdef SAFER
+ register_cipher (&safer_k64_desc);
+ register_cipher (&safer_sk64_desc);
+ register_cipher (&safer_k128_desc);
+ register_cipher (&safer_sk128_desc);
+#endif
+#ifdef RC2
+ register_cipher (&rc2_desc);
+#endif
+#ifdef DES
+ register_cipher (&des_desc);
+ register_cipher (&des3_desc);
+#endif
+#ifdef CAST5
+ register_cipher (&cast5_desc);
+#endif
+#ifdef NOEKEON
+ register_cipher (&noekeon_desc);
+#endif
+#ifdef SKIPJACK
+ register_cipher (&skipjack_desc);
+#endif
+#ifdef TIGER
+ register_hash (&tiger_desc);
+#endif
+#ifdef MD2
+ register_hash (&md2_desc);
+#endif
+#ifdef MD4
+ register_hash (&md4_desc);
+#endif
+#ifdef MD5
+ register_hash (&md5_desc);
+#endif
+#ifdef SHA1
+ register_hash (&sha1_desc);
+#endif
+#ifdef SHA256
+ register_hash (&sha256_desc);
+#endif
+#ifdef SHA224
+ register_hash (&sha224_desc);
+#endif
+#ifdef SHA384
+ register_hash (&sha384_desc);
+#endif
+#ifdef SHA512
+ register_hash (&sha512_desc);
+#endif
+#ifdef RIPEMD128
+ register_hash (&rmd128_desc);
+#endif
+#ifdef RIPEMD160
+ register_hash (&rmd160_desc);
+#endif
+#ifdef WHIRLPOOL
+ register_hash (&whirlpool_desc);
+#endif
+
+ if (register_prng(&yarrow_desc) == -1) {
+ printf("Error registering yarrow PRNG\n");
+ exit(-1);
+ }
+
+ if (register_prng(&sprng_desc) == -1) {
+ printf("Error registering sprng PRNG\n");
+ exit(-1);
+ }
+}
+
+/* sort tests based on their requirement/services. Helps make sure dependencies are tested first */
+void sort(void)
+{
+ unsigned x, y, z, a, pidx[26];
+
+ /* find out where things are provided */
+ zeromem(pidx, sizeof(pidx));
+ z = 0;
+ do {
+ y = 0;
+ for (x = 0; test_list[x].name != NULL; x++) {
+ if (test_list[x].entry == NULL) continue;
+ if (strlen(test_list[x].prov) == 0) {
+ y = 1;
+ tests[z++] = test_list[x]; test_list[x].entry = NULL;
+ pidx[test_list[x].prov[0]-'a'] = 1;
+ break;
+ } else {
+ for (a = 0; a < strlen(test_list[x].req); a++) {
+ if (pidx[test_list[x].req[a]-'a'] == 0) break;
+ }
+ if (a == strlen(test_list[x].req)) {
+ y = 1;
+ tests[z++] = test_list[x]; test_list[x].entry = NULL;
+ pidx[test_list[x].prov[0]-'a'] = 1;
+ break;
+ }
+ }
+ }
+ } while (y == 1);
+}
+
+int main(void)
+{
+ printf("Built with\n%s\n", crypt_build_settings);
+
+ srand(time(NULL));
+ sort();
+ register_algs();
+
+ // start dummy yarrow for internal use
+ DO(yarrow_start(&test_yarrow));
+ DO(yarrow_add_entropy("test", 4, &test_yarrow));
+ DO(yarrow_ready(&test_yarrow));
+
+ // do tests
+ for (current_test = 0; tests[current_test].name != NULL; current_test++) {
+ printf("[%-20s]: ", tests[current_test].name); fflush(stdout);
+ printf("\t%s\n", tests[current_test].entry()==0?"passed":"failed");
+ }
+
+ return 0;
+}
============================================================
--- demos/test/test.h ca8227f354a804ca3d084fae803b0993c37dbf5d
+++ demos/test/test.h ca8227f354a804ca3d084fae803b0993c37dbf5d
@@ -0,0 +1,29 @@
+#ifndef __TEST_H_
+#define __TEST_H_
+
+#include "mycrypt.h"
+
+typedef struct {
+ char *name, *prov, *req;
+ int (*entry)(void);
+} test_entry;
+
+extern prng_state test_yarrow;
+
+void run_cmd(int res, int line, char *file, char *cmd);
+#define DO(x) run_cmd((x), __LINE__, __FILE__, #x)
+
+
+
+/* TESTS */
+int cipher_hash_test(void);
+int modes_test(void);
+int mac_test(void);
+int pkcs_1_test(void);
+int store_test(void);
+int rsa_test(void);
+int ecc_tests(void);
+int dsa_test(void);
+int dh_tests(void);
+
+#endif
============================================================
# doc/crypt.pdf is binary
============================================================
--- error_to_string.c 4b53223659cd11cfedabf2dbd1ac1f00064ec812
+++ error_to_string.c 4b53223659cd11cfedabf2dbd1ac1f00064ec812
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+static const char *err_2_str[] =
+{
+ "CRYPT_OK",
+ "CRYPT_ERROR",
+ "Non-fatal 'no-operation' requested.",
+
+ "Invalid keysize for block cipher.",
+ "Invalid number of rounds for block cipher.",
+ "Algorithm failed test vectors.",
+
+ "Buffer overflow.",
+ "Invalid input packet.",
+
+ "Invalid number of bits for a PRNG.",
+ "Error reading the PRNG.",
+
+ "Invalid cipher specified.",
+ "Invalid hash specified.",
+ "Invalid PRNG specified.",
+
+ "Out of memory.",
+
+ "Invalid PK key or key type specified for function.",
+ "A private PK key is required.",
+
+ "Invalid argument provided.",
+ "File Not Found",
+
+ "Invalid PK type.",
+ "Invalid PK system.",
+ "Duplicate PK key found on keyring.",
+ "Key not found in keyring.",
+ "Invalid sized parameter.",
+
+ "Invalid size for prime.",
+
+};
+
+const char *error_to_string(int err)
+{
+ if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
+ return "Invalid error code.";
+ } else {
+ return err_2_str[err];
+ }
+}
+
============================================================
--- ltc_tommath.h c8e202d5b2b69feb8a255872514685eccf82bb03
+++ ltc_tommath.h c8e202d5b2b69feb8a255872514685eccf82bb03
@@ -0,0 +1,556 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#undef MIN
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#undef MAX
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define OPT_CAST(x) (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define OPT_CAST(x)
+
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+ typedef unsigned char mp_digit;
+ typedef unsigned short mp_word;
+#elif defined(MP_16BIT)
+ typedef unsigned short mp_digit;
+ typedef unsigned long mp_word;
+#elif defined(MP_64BIT)
+ /* for GCC only on supported platforms */
+#ifndef CRYPT
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+#endif
+
+ typedef ulong64 mp_digit;
+ typedef unsigned long mp_word __attribute__ ((mode(TI)));
+
+ #define DIGIT_BIT 60
+#else
+ /* this is the default case, 28-bit digits */
+
+ /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+ #if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 ulong64;
+ typedef signed __int64 long64;
+ #else
+ typedef unsigned long long ulong64;
+ typedef signed long long long64;
+ #endif
+#endif
+
+ typedef unsigned long mp_digit;
+ typedef ulong64 mp_word;
+
+#ifdef MP_31BIT
+ /* this is an extension that uses 31-bit digits */
+ #define DIGIT_BIT 31
+#else
+ /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+ #define DIGIT_BIT 28
+ #define MP_28BIT
+#endif
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+ /* default to libc stuff */
+ #ifndef XMALLOC
+ #define XMALLOC malloc
+ #define XFREE free
+ #define XREALLOC realloc
+ #define XCALLOC calloc
+ #else
+ /* prototypes for our heap functions */
+ extern void *XMALLOC(size_t n);
+ extern void *REALLOC(void *p, size_t n);
+ extern void *XCALLOC(size_t n, size_t s);
+ extern void XFREE(void *p);
+ #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+ #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT DIGIT_BIT
+#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX MP_MASK
+
+/* equalities */
+#define MP_LT -1 /* less than */
+#define MP_EQ 0 /* equal to */
+#define MP_GT 1 /* greater than */
+
+#define MP_ZPOS 0 /* positive integer */
+#define MP_NEG 1 /* negative */
+
+#define MP_OKAY 0 /* ok result */
+#define MP_MEM -2 /* out of mem */
+#define MP_VAL -3 /* invalid input */
+#define MP_RANGE MP_VAL
+
+#define MP_YES 1 /* yes response */
+#define MP_NO 0 /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS 0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
+#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */
+
+typedef int mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+ KARATSUBA_SQR_CUTOFF,
+ TOOM_MUL_CUTOFF,
+ TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+ #ifdef MP_LOW_MEM
+ #define MP_PREC 64 /* default digits of precision */
+ #else
+ #define MP_PREC 8 /* default digits of precision */
+ #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct {
+ int used, alloc, sign;
+ mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m) ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m) ((m)->sign)
+
+/* error code to char* string */
+char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime) */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+ #define PRIME_SIZE 31
+#else
+ #define PRIME_SIZE 256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit __prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases. Also performs an initial sieve of trial
+ * division. Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ * LTM_PRIME_BBS - make prime congruent to 3 mod 4
+ * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+
+int mp_read_radix(mp_int *a, char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp) mp_signed_bin_size(mp)
+#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S) mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
============================================================
--- modes_test.c 5fb32a2a1cdc4311654b80d027a10dbdcf09fc4b
+++ modes_test.c 5fb32a2a1cdc4311654b80d027a10dbdcf09fc4b
@@ -0,0 +1,46 @@
+/* test CFB/OFB/CBC modes */
+#include "test.h"
+
+int modes_test(void)
+{
+ unsigned char pt[64], ct[64], tmp[64], key[16], iv[16];
+ int x, cipher_idx;
+ symmetric_CBC cbc;
+
+ /* make a random pt, key and iv */
+ yarrow_read(pt, 64, &test_yarrow);
+ yarrow_read(key, 16, &test_yarrow);
+ yarrow_read(iv, 16, &test_yarrow);
+
+/* test CBC mode */
+ cipher_idx = find_cipher("aes");
+ if (cipher_idx == -1) {
+ printf("test requires AES");
+ return 1;
+ }
+
+
+ /* encode the block */
+ DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+ for (x = 0; x < 4; x++) {
+ DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc));
+ }
+
+ /* decode the block */
+ DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+ for (x = 0; x < 4; x++) {
+ DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc));
+ }
+ if (memcmp(tmp, pt, 64) != 0) {
+ printf("CBC failed");
+ return 1;
+ }
+
+/*
+ extern int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ int keylen, int num_rounds, symmetric_CBC *cbc);
+extern int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc);
+extern int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc);
+*/
+
+}
============================================================
--- mpi_to_ltc_error.c 7d237900c806bdaf1b45494089d37020aa4051f9
+++ mpi_to_ltc_error.c 7d237900c806bdaf1b45494089d37020aa4051f9
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MPI
+static const struct {
+ int mpi_code, ltc_code;
+} mpi_to_ltc_codes[] = {
+ { MP_OKAY , CRYPT_OK},
+ { MP_MEM , CRYPT_MEM},
+ { MP_VAL , CRYPT_INVALID_ARG},
+};
+
+/* convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) */
+int mpi_to_ltc_error(int err)
+{
+ int x;
+
+ for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
+ if (err == mpi_to_ltc_codes[x].mpi_code) {
+ return mpi_to_ltc_codes[x].ltc_code;
+ }
+ }
+ return CRYPT_ERROR;
+}
+#endif
+
============================================================
--- ofb_getiv.c 78815a65ad0934db29c875cf19333887ad1d46e5
+++ ofb_getiv.c 78815a65ad0934db29c875cf19333887ad1d46e5
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef OFB
+
+int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb)
+{
+ _ARGCHK(IV != NULL);
+ _ARGCHK(len != NULL);
+ _ARGCHK(ofb != NULL);
+ if ((unsigned long)ofb->blocklen > *len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ memcpy(IV, ofb->IV, ofb->blocklen);
+ *len = ofb->blocklen;
+
+ return CRYPT_OK;
+}
+
+#endif
============================================================
--- ofb_setiv.c 45017eac234d24e2f2f6c766f36ec6d7ff72788a
+++ ofb_setiv.c 45017eac234d24e2f2f6c766f36ec6d7ff72788a
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef OFB
+
+int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb)
+{
+ int err;
+
+ _ARGCHK(IV != NULL);
+ _ARGCHK(ofb != NULL);
+
+ if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len != (unsigned long)ofb->blocklen) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* force next block */
+ ofb->padlen = 0;
+ cipher_descriptor[ofb->cipher].ecb_encrypt(IV, ofb->IV, &ofb->key);
+ return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- pkcs_1_v15_es_decode.c 21f620c947db684ab3bc11e051edc1d0176086f4
+++ pkcs_1_v15_es_decode.c 21f620c947db684ab3bc11e051edc1d0176086f4
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* PKCS #1 v1.5 Encryption Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_es_decode(const unsigned char *msg, unsigned long msglen,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long outlen,
+ int *res)
+{
+ unsigned long x, modulus_bytelen;
+
+ _ARGCHK(msg != NULL);
+ _ARGCHK(out != NULL);
+ _ARGCHK(res != NULL);
+
+ /* default to failed */
+ *res = 0;
+
+ /* must be at least 12 bytes long */
+ if (msglen < 12) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* should start with 0x00 0x02 */
+ if (msg[0] != 0x00 || msg[1] != 0x02) {
+ return CRYPT_OK;
+ }
+
+ /* skip over PS */
+ x = 2 + (modulus_bytelen - outlen - 3);
+
+ /* should be 0x00 */
+ if (msg[x++] != 0x00) {
+ return CRYPT_OK;
+ }
+
+ /* the message is left */
+ if (x + outlen > modulus_bytelen) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+ memcpy(out, msg + x, outlen);
+ *res = 1;
+ return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- pkcs_1_v15_es_encode.c fb6d3ddfe5810de3c92b46edb0f4c8a7b6de615b
+++ pkcs_1_v15_es_encode.c fb6d3ddfe5810de3c92b46edb0f4c8a7b6de615b
@@ -0,0 +1,55 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* v1.5 Encryption Padding for PKCS #1 -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_es_encode(const unsigned char *msg, unsigned long msglen,
+ unsigned long modulus_bitlen,
+ prng_state *prng, int prng_idx,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long modulus_bytelen, x, y;
+
+ _ARGCHK(msg != NULL);
+ _ARGCHK(out != NULL);
+ _ARGCHK(outlen != NULL);
+
+ /* get modulus len */
+ modulus_bytelen = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+ if (modulus_bytelen < 12) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* verify length */
+ if (msglen > (modulus_bytelen - 11) || *outlen < modulus_bytelen) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* 0x00 0x02 PS 0x00 M */
+ x = 0;
+ out[x++] = 0x00;
+ out[x++] = 0x02;
+ y = modulus_bytelen - msglen - 3;
+ if (prng_descriptor[prng_idx].read(out+x, y, prng) != y) {
+ return CRYPT_ERROR_READPRNG;
+ }
+ x += y;
+ out[x++] = 0x00;
+ memcpy(out+x, msg, msglen);
+ *outlen = modulus_bytelen;
+
+ return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
============================================================
--- pkcs_1_v15_sa_decode.c 4f6aeaa76927807827ad5a472b8e84d600f9f6cd
+++ pkcs_1_v15_sa_decode.c 4f6aeaa76927807827ad5a472b8e84d600f9f6cd
@@ -0,0 +1,77 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* PKCS #1 v1.5 Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ int hash_idx, unsigned long modulus_bitlen,
+ int *res)
+{
+ unsigned long x, y, modulus_bytelen, derlen;
+ int err;
+
+ _ARGCHK(msghash != NULL);
+ _ARGCHK(sig != NULL);
+ _ARGCHK(res != NULL);
+
+ /* default to invalid */
+ *res = 0;
+
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get derlen */
+ derlen = hash_descriptor[hash_idx].DERlen;
+
+ /* get modulus len */
+ modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* valid sizes? */
+ if ((msghashlen + 3 + derlen > modulus_bytelen) || (siglen != modulus_bytelen)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */
+ x = 0;
+ if (sig[x++] != 0x00 || sig[x++] != 0x01) {
+ return CRYPT_OK;
+ }
+
+ /* now follows (modulus_bytelen - 3 - derlen - msghashlen) 0xFF bytes */
+ for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) {
+ if (sig[x++] != 0xFF) {
+ return CRYPT_OK;
+ }
+ }
+
+ if (sig[x++] != 0x00) {
+ return CRYPT_OK;
+ }
+
+ for (y = 0; y < derlen; y++) {
+ if (sig[x++] != hash_descriptor[hash_idx].DER[y]) {
+ return CRYPT_OK;
+ }
+ }
+
+ if (memcmp(msghash, sig+x, msghashlen) == 0) {
+ *res = 1;
+ }
+ return CRYPT_OK;
+}
+
+#endif
============================================================
--- pkcs_1_v15_sa_encode.c 0f05185ad6c209d813573788e5cf5057e9dbaf66
+++ pkcs_1_v15_sa_encode.c 0f05185ad6c209d813573788e5cf5057e9dbaf66
@@ -0,0 +1,71 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* PKCS #1 v1.5 Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_sa_encode(const unsigned char *msghash, unsigned long msghashlen,
+ int hash_idx, unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long derlen, modulus_bytelen, x, y;
+ int err;
+
+ _ARGCHK(msghash != NULL)
+ _ARGCHK(out != NULL);
+ _ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* hack, to detect any hash without a DER OID */
+ if (hash_descriptor[hash_idx].DERlen == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* get modulus len */
+ modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* get der len ok? Forgive my lame German accent.... */
+ derlen = hash_descriptor[hash_idx].DERlen;
+
+ /* valid sizes? */
+ if (msghashlen + 3 + derlen > modulus_bytelen) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ if (*outlen < modulus_bytelen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */
+ x = 0;
+ out[x++] = 0x00;
+ out[x++] = 0x01;
+ for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) {
+ out[x++] = 0xFF;
+ }
+ out[x++] = 0x00;
+ for (y = 0; y < derlen; y++) {
+ out[x++] = hash_descriptor[hash_idx].DER[y];
+ }
+ for (y = 0; y < msghashlen; y++) {
+ out[x++] = msghash[y];
+ }
+
+ *outlen = modulus_bytelen;
+ return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
============================================================
--- rsa_decrypt_key.c 471c35e6305e3e3a7819d08525526b0019248723
+++ rsa_decrypt_key.c 471c35e6305e3e3a7819d08525526b0019248723
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* decrypt then OAEP depad */
+int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *outkey, unsigned long *keylen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ prng_state *prng, int prng_idx,
+ int hash_idx, int *res,
+ rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ _ARGCHK(outkey != NULL);
+ _ARGCHK(keylen != NULL);
+ _ARGCHK(key != NULL);
+ _ARGCHK(res != NULL);
+
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen != inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* rsa decode the packet */
+ x = *keylen;
+ if ((err = rsa_exptmod(in, inlen, outkey, &x, PK_PRIVATE, prng, prng_idx, key)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* now OAEP decode the packet */
+ return pkcs_1_oaep_decode(outkey, x, lparam, lparamlen, modulus_bitlen, hash_idx,
+ outkey, keylen, res);
+}
+
+#endif /* MRSA */
+
+
+
+
============================================================
--- rsa_encrypt_key.c 1ca9226d54ce36a9e700000145db98a22b3753d5
+++ rsa_encrypt_key.c 1ca9226d54ce36a9e700000145db98a22b3753d5
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* OAEP pad then encrypt */
+int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
+ unsigned char *outkey, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ prng_state *prng, int prng_idx, int hash_idx, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ _ARGCHK(inkey != NULL);
+ _ARGCHK(outkey != NULL);
+ _ARGCHK(outlen != NULL);
+ _ARGCHK(key != NULL);
+
+ /* valid prng and hash ? */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen > *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* OAEP pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_oaep_encode(inkey, inlen, lparam,
+ lparamlen, modulus_bitlen, prng, prng_idx, hash_idx,
+ outkey, &x)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* rsa exptmod the OAEP pad */
+ return rsa_exptmod(outkey, x, outkey, outlen, PK_PUBLIC, prng, prng_idx, key);
+}
+
+#endif /* MRSA */
============================================================
--- rsa_export.c 520f23951ac1fd1e28ab14a9283ef84abacc8baa
+++ rsa_export.c 520f23951ac1fd1e28ab14a9283ef84abacc8baa
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
+{
+ unsigned long y, z;
+ int err;
+
+ _ARGCHK(out != NULL);
+ _ARGCHK(outlen != NULL);
+ _ARGCHK(key != NULL);
+
+ /* can we store the static header? */
+ if (*outlen < (PACKET_SIZE + 1)) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* type valid? */
+ if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) &&
+ (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* start at offset y=PACKET_SIZE */
+ y = PACKET_SIZE;
+
+ /* output key type */
+ out[y++] = type;
+
+ /* output modulus */
+ OUTPUT_BIGNUM(&key->N, out, y, z);
+
+ /* output public key */
+ OUTPUT_BIGNUM(&key->e, out, y, z);
+
+ if (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED) {
+ OUTPUT_BIGNUM(&key->d, out, y, z);
+ }
+
+ if (type == PK_PRIVATE_OPTIMIZED) {
+ OUTPUT_BIGNUM(&key->dQ, out, y, z);
+ OUTPUT_BIGNUM(&key->dP, out, y, z);
+ OUTPUT_BIGNUM(&key->pQ, out, y, z);
+ OUTPUT_BIGNUM(&key->qP, out, y, z);
+ OUTPUT_BIGNUM(&key->p, out, y, z);
+ OUTPUT_BIGNUM(&key->q, out, y, z);
+ }
+
+ /* store packet header */
+ packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_KEY);
+
+ /* copy to the user buffer */
+ *outlen = y;
+
+ /* clear stack and return */
+ return CRYPT_OK;
+}
+
+#endif /* MRSA */
+
============================================================
--- rsa_import.c 4a7e1456f13ac5313a999164c2f7e41022c3419b
+++ rsa_import.c 4a7e1456f13ac5313a999164c2f7e41022c3419b
@@ -0,0 +1,81 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ unsigned long x, y;
+ int err;
+
+ _ARGCHK(in != NULL);
+ _ARGCHK(key != NULL);
+
+ /* check length */
+ if (inlen < (1+PACKET_SIZE)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* test packet header */
+ if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* init key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,
+ &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+ return mpi_to_ltc_error(err);
+ }
+
+ /* get key type */
+ y = PACKET_SIZE;
+ key->type = (int)in[y++];
+
+ /* load the modulus */
+ INPUT_BIGNUM(&key->N, in, x, y, inlen);
+
+ /* load public exponent */
+ INPUT_BIGNUM(&key->e, in, x, y, inlen);
+
+ /* get private exponent */
+ if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) {
+ INPUT_BIGNUM(&key->d, in, x, y, inlen);
+ }
+
+ /* get CRT private data if required */
+ if (key->type == PK_PRIVATE_OPTIMIZED) {
+ INPUT_BIGNUM(&key->dQ, in, x, y, inlen);
+ INPUT_BIGNUM(&key->dP, in, x, y, inlen);
+ INPUT_BIGNUM(&key->pQ, in, x, y, inlen);
+ INPUT_BIGNUM(&key->qP, in, x, y, inlen);
+ INPUT_BIGNUM(&key->p, in, x, y, inlen);
+ INPUT_BIGNUM(&key->q, in, x, y, inlen);
+ }
+
+ /* free up ram not required */
+ if (key->type != PK_PRIVATE_OPTIMIZED) {
+ mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL);
+ }
+ if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+ mp_clear(&key->d);
+ }
+
+ return CRYPT_OK;
+error:
+ mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
+ &key->pQ, &key->qP, &key->p, &key->q, NULL);
+ return err;
+}
+
+#endif /* MRSA */
+
============================================================
--- rsa_sign_hash.c d3856ae248e093d7f73f48dee96911f2293cd4a5
+++ rsa_sign_hash.c d3856ae248e093d7f73f48dee96911f2293cd4a5
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* PSS pad then sign */
+int rsa_sign_hash(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned char *sig, unsigned long *siglen,
+ prng_state *prng, int prng_idx,
+ int hash_idx, unsigned long saltlen,
+ rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ _ARGCHK(msghash != NULL);
+ _ARGCHK(sig != NULL);
+ _ARGCHK(siglen != NULL);
+ _ARGCHK(key != NULL);
+
+ /* valid prng and hash ? */
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen > *siglen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* PSS pad the key */
+ x = *siglen;
+ if ((err = pkcs_1_pss_encode(msghash, msghashlen, saltlen, prng, prng_idx,
+ hash_idx, modulus_bitlen, sig, &x)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* RSA encode it */
+ return rsa_exptmod(sig, x, sig, siglen, PK_PRIVATE, prng, prng_idx, key);
+}
+
+#endif /* MRSA */
============================================================
--- rsa_verify_hash.c a1667bf6fa35453ae0b69bfec574ab3c39525935
+++ rsa_verify_hash.c a1667bf6fa35453ae0b69bfec574ab3c39525935
@@ -0,0 +1,69 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* design then PSS depad */
+int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *msghash, unsigned long msghashlen,
+ prng_state *prng, int prng_idx,
+ int hash_idx, unsigned long saltlen,
+ int *stat, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmpbuf;
+
+ _ARGCHK(msghash != NULL);
+ _ARGCHK(sig != NULL);
+ _ARGCHK(stat != NULL);
+ _ARGCHK(key != NULL);
+
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits(&(key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+ if (modulus_bytelen != siglen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate temp buffer for decoded sig */
+ tmpbuf = XCALLOC(1, modulus_bytelen + 1);
+ if (tmpbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* RSA decode it */
+ x = siglen;
+ if ((err = rsa_exptmod(sig, siglen, tmpbuf, &x, PK_PUBLIC, prng, prng_idx, key)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ return err;
+ }
+
+ /* PSS decode it */
+ err = pkcs_1_pss_decode(msghash, msghashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+ XFREE(tmpbuf);
+ return err;
+}
+
+#endif /* MRSA */
============================================================
--- tim_exptmod.c 80dfac51cb0dd33e4d80702187313fc7d96d52d4
+++ tim_exptmod.c 80dfac51cb0dd33e4d80702187313fc7d96d52d4
@@ -0,0 +1,77 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+/* RSA Code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef RSA_TIMING
+
+/* decrypts c into m */
+int tim_exptmod(prng_state *prng, int prng_idx,
+ mp_int *c, mp_int *e, mp_int *d, mp_int *n, mp_int *m)
+{
+ int err;
+ mp_int r, tmp, tmp2;
+ unsigned char *rtmp;
+ unsigned long rlen;
+
+ _ARGCHK(c != NULL);
+ _ARGCHK(e != NULL);
+ _ARGCHK(d != NULL);
+ _ARGCHK(n != NULL);
+ _ARGCHK(m != NULL);
+
+ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* pick random r */
+ rtmp = XMALLOC(MAX_RSA_SIZE/8);
+ if (rtmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+
+ rlen = mp_unsigned_bin_size(n);
+ if (prng_descriptor[prng_idx].read(rtmp, rlen, prng) != rlen) {
+ XFREE(rtmp);
+ return CRYPT_ERROR_READPRNG;
+ }
+
+ if ((err = mp_init_multi(&r, &tmp, &tmp2, NULL)) != MP_OKAY) {
+ XFREE(rtmp);
+ return mpi_to_ltc_error(err);
+ }
+
+ /* read in r */
+ if ((err = mp_read_unsigned_bin(&r, rtmp, rlen)) != MP_OKAY) { goto __ERR; }
+
+ /* compute tmp = r^e */
+ if ((err = mp_exptmod(&r, e, n, &tmp)) != MP_OKAY) { goto __ERR; }
+
+ /* multiply C into the mix */
+ if ((err = mp_mulmod(c, &tmp, n, &tmp)) != MP_OKAY) { goto __ERR; }
+
+ /* raise to d */
+ if ((err = mp_exptmod(&tmp, d, n, &tmp)) != MP_OKAY) { goto __ERR; }
+
+ /* invert r and multiply */
+ if ((err = mp_invmod(&r, n, &tmp2)) != MP_OKAY) { goto __ERR; }
+
+ /* multiply and we are totally set */
+ if ((err = mp_mulmod(&tmp, &tmp2, n, m)) != MP_OKAY) { goto __ERR; }
+
+__ERR: mp_clear_multi(&r, &tmp, &tmp2, NULL);
+ XFREE(rtmp);
+ return mpi_to_ltc_error(err);
+}
+
+#endif
============================================================
--- aes.c decb06209890d202bdaa2b2095344580bb9d4b13
+++ aes.c 34c70069a1c05c3e8d6e42f1ef10495b271f425d
@@ -30,16 +30,20 @@
#ifdef RIJNDAEL
+#ifndef ENCRYPT_ONLY
+
+#define SETUP rijndael_setup
+#define ECB_ENC rijndael_ecb_encrypt
+#define ECB_DEC rijndael_ecb_decrypt
+#define ECB_TEST rijndael_test
+#define ECB_KS rijndael_keysize
+
const struct _cipher_descriptor rijndael_desc =
{
"rijndael",
6,
16, 32, 16, 10,
- &rijndael_setup,
- &rijndael_ecb_encrypt,
- &rijndael_ecb_decrypt,
- &rijndael_test,
- &rijndael_keysize
+ SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_KS
};
const struct _cipher_descriptor aes_desc =
@@ -47,21 +51,63 @@ const struct _cipher_descriptor aes_desc
"aes",
6,
16, 32, 16, 10,
- &rijndael_setup,
- &rijndael_ecb_encrypt,
- &rijndael_ecb_decrypt,
- &rijndael_test,
- &rijndael_keysize
+ SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_KS
};
+#else
+
+#define SETUP rijndael_enc_setup
+#define ECB_ENC rijndael_enc_ecb_encrypt
+#define ECB_KS rijndael_enc_keysize
+
+const struct _cipher_descriptor rijndael_enc_desc =
+{
+ "rijndael",
+ 6,
+ 16, 32, 16, 10,
+ SETUP, ECB_ENC, NULL, NULL, ECB_KS
+};
+
+const struct _cipher_descriptor aes_enc_desc =
+{
+ "aes",
+ 6,
+ 16, 32, 16, 10,
+ SETUP, ECB_ENC, NULL, NULL, ECB_KS
+};
+
+#endif
+
#include "aes_tab.c"
-int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
+static ulong32 setup_mix(ulong32 temp)
{
+ return (Te4_3[byte(temp, 2)]) ^
+ (Te4_2[byte(temp, 1)]) ^
+ (Te4_1[byte(temp, 0)]) ^
+ (Te4_0[byte(temp, 3)]);
+}
+
+#ifndef ENCRYPT_ONLY
+
+static ulong32 setup_mix2(ulong32 temp)
+{
+ return Td0(255 & Te4[byte(temp, 3)]) ^
+ Td1(255 & Te4[byte(temp, 2)]) ^
+ Td2(255 & Te4[byte(temp, 1)]) ^
+ Td3(255 & Te4[byte(temp, 0)]);
+}
+
+#endif
+
+int SETUP(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
+{
int i, j;
- ulong32 temp, *rk, *rrk;
-
- _ARGCHK(key != NULL);
+ ulong32 temp, *rk;
+#ifndef ENCRYPT_ONLY
+ ulong32 *rrk;
+#endif
+ _ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (keylen != 16 && keylen != 24 && keylen != 32) {
@@ -85,12 +131,7 @@ int rijndael_setup(const unsigned char *
j = 44;
for (;;) {
temp = rk[3];
- rk[4] = rk[0] ^
- (Te4_3[byte(temp, 2)]) ^
- (Te4_2[byte(temp, 1)]) ^
- (Te4_1[byte(temp, 0)]) ^
- (Te4_0[byte(temp, 3)]) ^
- rcon[i];
+ rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
@@ -109,12 +150,7 @@ int rijndael_setup(const unsigned char *
#else
temp = rk[5];
#endif
- rk[ 6] = rk[ 0] ^
- (Te4_3[byte(temp, 2)]) ^
- (Te4_2[byte(temp, 1)]) ^
- (Te4_1[byte(temp, 0)]) ^
- (Te4_0[byte(temp, 3)]) ^
- rcon[i];
+ rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
rk[ 7] = rk[ 1] ^ rk[ 6];
rk[ 8] = rk[ 2] ^ rk[ 7];
rk[ 9] = rk[ 3] ^ rk[ 8];
@@ -137,12 +173,7 @@ int rijndael_setup(const unsigned char *
#else
temp = rk[7];
#endif
- rk[ 8] = rk[ 0] ^
- (Te4_3[byte(temp, 2)]) ^
- (Te4_2[byte(temp, 1)]) ^
- (Te4_1[byte(temp, 0)]) ^
- (Te4_0[byte(temp, 3)]) ^
- rcon[i];
+ rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
rk[ 9] = rk[ 1] ^ rk[ 8];
rk[10] = rk[ 2] ^ rk[ 9];
rk[11] = rk[ 3] ^ rk[10];
@@ -150,11 +181,7 @@ int rijndael_setup(const unsigned char *
break;
}
temp = rk[11];
- rk[12] = rk[ 4] ^
- (Te4_3[byte(temp, 3)]) ^
- (Te4_2[byte(temp, 2)]) ^
- (Te4_1[byte(temp, 1)]) ^
- (Te4_0[byte(temp, 0)]);
+ rk[12] = rk[ 4] ^ setup_mix(ROR(temp, 8));
rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
@@ -164,7 +191,8 @@ int rijndael_setup(const unsigned char *
/* this can't happen */
j = 4;
}
-
+
+#ifndef ENCRYPT_ONLY
/* setup the inverse key now */
rk = skey->rijndael.dK;
rrk = skey->rijndael.eK + j - 4;
@@ -182,29 +210,13 @@ int rijndael_setup(const unsigned char *
rk += 4;
#ifdef SMALL_CODE
temp = rrk[0];
- rk[0] =
- Td0(255 & Te4[byte(temp, 3)]) ^
- Td1(255 & Te4[byte(temp, 2)]) ^
- Td2(255 & Te4[byte(temp, 1)]) ^
- Td3(255 & Te4[byte(temp, 0)]);
+ rk[0] = setup_mix2(temp);
temp = rrk[1];
- rk[1] =
- Td0(255 & Te4[byte(temp, 3)]) ^
- Td1(255 & Te4[byte(temp, 2)]) ^
- Td2(255 & Te4[byte(temp, 1)]) ^
- Td3(255 & Te4[byte(temp, 0)]);
+ rk[1] = setup_mix2(temp);
temp = rrk[2];
- rk[2] =
- Td0(255 & Te4[byte(temp, 3)]) ^
- Td1(255 & Te4[byte(temp, 2)]) ^
- Td2(255 & Te4[byte(temp, 1)]) ^
- Td3(255 & Te4[byte(temp, 0)]);
+ rk[2] = setup_mix2(temp);
temp = rrk[3];
- rk[3] =
- Td0(255 & Te4[byte(temp, 3)]) ^
- Td1(255 & Te4[byte(temp, 2)]) ^
- Td2(255 & Te4[byte(temp, 1)]) ^
- Td3(255 & Te4[byte(temp, 0)]);
+ rk[3] = setup_mix2(temp);
#else
temp = rrk[0];
rk[0] =
@@ -241,6 +253,7 @@ int rijndael_setup(const unsigned char *
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk = *rrk;
+#endif /* ENCRYPT_ONLY */
return CRYPT_OK;
}
@@ -248,7 +261,7 @@ static void _rijndael_ecb_encrypt(const
#ifdef CLEAN_STACK
static void _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
#else
-void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+void ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
#endif
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
@@ -270,6 +283,44 @@ void rijndael_ecb_encrypt(const unsigned
LOAD32H(s2, pt + 8); s2 ^= rk[2];
LOAD32H(s3, pt + 12); s3 ^= rk[3];
+
+#ifdef SMALL_CODE
+
+ for (r = 0; ; r++) {
+ rk += 4;
+ t0 =
+ Te0(byte(s0, 3)) ^
+ Te1(byte(s1, 2)) ^
+ Te2(byte(s2, 1)) ^
+ Te3(byte(s3, 0)) ^
+ rk[0];
+ t1 =
+ Te0(byte(s1, 3)) ^
+ Te1(byte(s2, 2)) ^
+ Te2(byte(s3, 1)) ^
+ Te3(byte(s0, 0)) ^
+ rk[1];
+ t2 =
+ Te0(byte(s2, 3)) ^
+ Te1(byte(s3, 2)) ^
+ Te2(byte(s0, 1)) ^
+ Te3(byte(s1, 0)) ^
+ rk[2];
+ t3 =
+ Te0(byte(s3, 3)) ^
+ Te1(byte(s0, 2)) ^
+ Te2(byte(s1, 1)) ^
+ Te3(byte(s2, 0)) ^
+ rk[3];
+ if (r == Nr-2) {
+ break;
+ }
+ s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+ }
+ rk += 4;
+
+#else
+
/*
* Nr - 1 full rounds:
*/
@@ -330,52 +381,57 @@ void rijndael_ecb_encrypt(const unsigned
Te3(byte(t2, 0)) ^
rk[3];
}
+
+#endif
+
/*
* apply last round and
* map cipher state to byte array block:
*/
s0 =
- (Te4_3[(t0 >> 24) ]) ^
- (Te4_2[(t1 >> 16) & 0xff]) ^
- (Te4_1[(t2 >> 8) & 0xff]) ^
- (Te4_0[(t3 ) & 0xff]) ^
+ (Te4_3[byte(t0, 3)]) ^
+ (Te4_2[byte(t1, 2)]) ^
+ (Te4_1[byte(t2, 1)]) ^
+ (Te4_0[byte(t3, 0)]) ^
rk[0];
STORE32H(s0, ct);
s1 =
- (Te4_3[(t1 >> 24) ]) ^
- (Te4_2[(t2 >> 16) & 0xff]) ^
- (Te4_1[(t3 >> 8) & 0xff]) ^
- (Te4_0[(t0 ) & 0xff]) ^
+ (Te4_3[byte(t1, 3)]) ^
+ (Te4_2[byte(t2, 2)]) ^
+ (Te4_1[byte(t3, 1)]) ^
+ (Te4_0[byte(t0, 0)]) ^
rk[1];
STORE32H(s1, ct+4);
s2 =
- (Te4_3[(t2 >> 24) ]) ^
- (Te4_2[(t3 >> 16) & 0xff]) ^
- (Te4_1[(t0 >> 8) & 0xff]) ^
- (Te4_0[(t1 ) & 0xff]) ^
+ (Te4_3[byte(t2, 3)]) ^
+ (Te4_2[byte(t3, 2)]) ^
+ (Te4_1[byte(t0, 1)]) ^
+ (Te4_0[byte(t1, 0)]) ^
rk[2];
STORE32H(s2, ct+8);
s3 =
- (Te4_3[(t3 >> 24) ]) ^
- (Te4_2[(t0 >> 16) & 0xff]) ^
- (Te4_1[(t1 >> 8) & 0xff]) ^
- (Te4_0[(t2 ) & 0xff]) ^
+ (Te4_3[byte(t3, 3)]) ^
+ (Te4_2[byte(t0, 2)]) ^
+ (Te4_1[byte(t1, 1)]) ^
+ (Te4_0[byte(t2, 0)]) ^
rk[3];
STORE32H(s3, ct+12);
}
#ifdef CLEAN_STACK
-void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+void ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
{
_rijndael_ecb_encrypt(pt, ct, skey);
burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
}
#endif
+#ifndef ENCRYPT_ONLY
+
#ifdef CLEAN_STACK
static void _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
#else
-void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+void ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
#endif
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
@@ -397,6 +453,42 @@ void rijndael_ecb_decrypt(const unsigned
LOAD32H(s2, ct + 8); s2 ^= rk[2];
LOAD32H(s3, ct + 12); s3 ^= rk[3];
+#ifdef SMALL_CODE
+ for (r = 0; ; r++) {
+ rk += 4;
+ t0 =
+ Td0(byte(s0, 3)) ^
+ Td1(byte(s3, 2)) ^
+ Td2(byte(s2, 1)) ^
+ Td3(byte(s1, 0)) ^
+ rk[0];
+ t1 =
+ Td0(byte(s1, 3)) ^
+ Td1(byte(s0, 2)) ^
+ Td2(byte(s3, 1)) ^
+ Td3(byte(s2, 0)) ^
+ rk[1];
+ t2 =
+ Td0(byte(s2, 3)) ^
+ Td1(byte(s1, 2)) ^
+ Td2(byte(s0, 1)) ^
+ Td3(byte(s3, 0)) ^
+ rk[2];
+ t3 =
+ Td0(byte(s3, 3)) ^
+ Td1(byte(s2, 2)) ^
+ Td2(byte(s1, 1)) ^
+ Td3(byte(s0, 0)) ^
+ rk[3];
+ if (r == Nr-2) {
+ break;
+ }
+ s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+ }
+ rk += 4;
+
+#else
+
/*
* Nr - 1 full rounds:
*/
@@ -459,51 +551,52 @@ void rijndael_ecb_decrypt(const unsigned
Td3(byte(t0, 0)) ^
rk[3];
}
+#endif
/*
* apply last round and
* map cipher state to byte array block:
*/
s0 =
- (Td4[(t0 >> 24) ] & 0xff000000) ^
- (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t1 ) & 0xff] & 0x000000ff) ^
+ (Td4[byte(t0, 3)] & 0xff000000) ^
+ (Td4[byte(t3, 2)] & 0x00ff0000) ^
+ (Td4[byte(t2, 1)] & 0x0000ff00) ^
+ (Td4[byte(t1, 0)] & 0x000000ff) ^
rk[0];
STORE32H(s0, pt);
s1 =
- (Td4[(t1 >> 24) ] & 0xff000000) ^
- (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t2 ) & 0xff] & 0x000000ff) ^
+ (Td4[byte(t1, 3)] & 0xff000000) ^
+ (Td4[byte(t0, 2)] & 0x00ff0000) ^
+ (Td4[byte(t3, 1)] & 0x0000ff00) ^
+ (Td4[byte(t2, 0)] & 0x000000ff) ^
rk[1];
STORE32H(s1, pt+4);
s2 =
- (Td4[(t2 >> 24) ] & 0xff000000) ^
- (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t3 ) & 0xff] & 0x000000ff) ^
+ (Td4[byte(t2, 3)] & 0xff000000) ^
+ (Td4[byte(t1, 2)] & 0x00ff0000) ^
+ (Td4[byte(t0, 1)] & 0x0000ff00) ^
+ (Td4[byte(t3, 0)] & 0x000000ff) ^
rk[2];
STORE32H(s2, pt+8);
s3 =
- (Td4[(t3 >> 24) ] & 0xff000000) ^
- (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t0 ) & 0xff] & 0x000000ff) ^
+ (Td4[byte(t3, 3)] & 0xff000000) ^
+ (Td4[byte(t2, 2)] & 0x00ff0000) ^
+ (Td4[byte(t1, 1)] & 0x0000ff00) ^
+ (Td4[byte(t0, 0)] & 0x000000ff) ^
rk[3];
STORE32H(s3, pt+12);
}
#ifdef CLEAN_STACK
-void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+void ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
{
_rijndael_ecb_decrypt(ct, pt, skey);
burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
}
#endif
-int rijndael_test(void)
+int ECB_TEST(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
@@ -584,7 +677,9 @@ int rijndael_test(void)
#endif
}
-int rijndael_keysize(int *desired_keysize)
+#endif /* ENCRYPT_ONLY */
+
+int ECB_KS(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
============================================================
--- aes_tab.c 026d6575ce571ca3ca33e828c9c7c75dc787c696
+++ aes_tab.c 8d84d7ccee23e01c4a8f876735478b5a44d4bd42
@@ -157,6 +157,8 @@ static const ulong32 Te4[256] = {
0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
};
+#ifndef ENCRYPT_ONLY
+
static const ulong32 TD0[256] = {
0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
@@ -291,6 +293,8 @@ static const ulong32 Td4[256] = {
0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
};
+#endif /* ENCRYPT_ONLY */
+
#ifdef SMALL_CODE
#define Te0(x) TE0[x]
@@ -660,6 +664,8 @@ 0x41000000UL, 0x99000000UL, 0x2d000000UL
0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
};
+#ifndef ENCRYPT_ONLY
+
static const ulong32 TD1[256] = {
0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
@@ -999,6 +1005,8 @@ 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL
0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
};
+#endif /* ENCRYPT_ONLY */
+
#endif /* SMALL CODE */
static const ulong32 rcon[] = {
============================================================
--- cbc_decrypt.c f6a28de38f7e35337bc38c2f5a81e60cdc104a05
+++ cbc_decrypt.c 290fb8f65b1037f8479d118dd94340458eeaed8d
@@ -25,14 +25,15 @@ int cbc_decrypt(const unsigned char *ct,
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err;
}
- cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
-
+ _ARGCHK(cipher_descriptor[cbc->cipher].ecb_decrypt != NULL);
+
/* is blocklen valid? */
if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) {
return CRYPT_INVALID_ARG;
}
- /* xor IV against the plaintext of the previous step */
+ /* decrypt and xor IV against the plaintext of the previous step */
+ cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
for (x = 0; x < cbc->blocklen; x++) {
/* copy CT in case ct == pt */
tmp2[x] = ct[x];
============================================================
--- changes 1dfeb3f2aedcb7f984297fb7d4a7afdbff1cb674
+++ changes b68f47aa1ca092c730b59b38f794c822f473902e
@@ -1,3 +1,28 @@
+May 30th, 2004
+v0.96 -- Removed GF and Keyring code
+ -- Extended OAEP decoder to distinguish better [and use a more uniform API]
+ -- Changed PSS/OAEP API slightly to be more consistent with other PK functions (order of arguments)
+ -- rsa_exptmod() now pads with leading zeroes as per I2OSP.
+ -- added error checking to yarrow code
+ -- Mike Frysinger pointed out that tommath.h from this distro will overwrite tommath.h
+ from libtommath. I changed this to ltc_tommath.h to avoid any such problems.
+ -- Fixed bug in PSS encoder/decoder that didn't handle the MSB properly
+ -- refactored AES, now sports an "encrypt only" descriptor which uses half as much code space.
+ -- modded Yarrow to try and use refactored AES code and added WHIRLPOOL support (d'oh) ;-)
+ -- updated ECB, OCB and CBC decrypt functions to detect when "encrypt only" descriptor is used.
+ -- replaced old RSA code with new code that uses PKCS #1 v2.0 padding
+ -- replaced old test harness with new over-engineer'ed one in /demos/test/
+ -- updated cbc/cfb/ofb/ctr code with setiv/getiv functions to change/read the IV without re-keying.
+ -- Added PKCS #1 v1.5 RSA encryption and signature padding routines
+ -- Added DER OID's to most hash descriptors (as many as I could find)
+ -- modded rsa_exptmod() to use timing-resilient tim_exptmod() when doing private key operations
+ added #define RSA_TIMING which can turn on/off this feature.
+ -- No more config.pl so please just read mycrypt_custom.h for build-time tweaks
+ -- Small update to rand_prime()
+ -- Updated sha1, md5 and sha256 so they are smaller when SMALL_CODE is defined. If you want speed though,
+ you're going to have to undefine SMALL_CODE ;-)
+ -- Worked over AES so that it's even smaller now [in both modes].
+
May 12th, 2004
v0.95 -- Optimized AES and WHIRLPOOL for SMALL_CODE by taking advantage of the fact
the transforms are circulant. AES dropped 5KB and WHIRLPOOL dropped 13KB
============================================================
--- crypt.c c1c89e3e4d520f3674362686f4b2eb652350c71f
+++ crypt.c 14fd6a0ac48eea8e092891cc828a900b55682689
@@ -120,6 +120,9 @@ const char *crypt_build_settings =
#if defined(RIPEMD160)
" RIPEMD160\n"
#endif
+#if defined(WHIRLPOOL)
+ " WHIRLPOOL\n"
+#endif
"\nBlock Chaining Modes:\n"
#if defined(CFB)
@@ -151,8 +154,12 @@ const char *crypt_build_settings =
"\nPK Algs:\n"
#if defined(MRSA)
- " RSA\n"
+ " RSA"
+#if defined(RSA_TIMING)
+ " + RSA_TIMING "
#endif
+ "\n"
+#endif
#if defined(MDH)
" DH\n"
#endif
@@ -162,9 +169,6 @@ const char *crypt_build_settings =
#if defined(MDSA)
" DSA\n"
#endif
-#if defined(KR)
- " KR\n"
-#endif
"\nCompiler:\n"
#if defined(WIN32)
@@ -187,9 +191,6 @@ const char *crypt_build_settings =
#endif
"\nVarious others: "
-#if defined(GF)
- " GF "
-#endif
#if defined(BASE64)
" BASE64 "
#endif
@@ -223,6 +224,15 @@ const char *crypt_build_settings =
#if defined(PKCS_5)
" PKCS#5 "
#endif
+#if defined(SMALL_CODE)
+ " SMALL_CODE "
+#endif
+#if defined(NO_FILE)
+ " NO_FILE "
+#endif
+#if defined(LTC_TEST)
+ " LTC_TEST "
+#endif
"\n"
"\n\n\n"
;
============================================================
--- crypt.tex 8e63225b182ba100c6698dcea5381fb0debcb46e
+++ crypt.tex f230cd06ff9351b7e4a36fa9a6932a55cedc295f
@@ -47,7 +47,7 @@
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
-\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.95}
+\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.96}
\author{Tom St Denis \\
\\
tomstdenis@iahu.ca \\
@@ -103,7 +103,8 @@ \subsection{What the library IS for?}
The library also serves well as a toolkit for applications where they don't need to be OpenPGP, PKCS, etc. compliant.
Included are fully operational public key routines for encryption, decryption, signature generation and verification.
-These routines are fully portable but are not conformant to any known set of standards. They are all based on established
+These routines are fully portable but are not conformant to any known set of standards\footnote{With the exception of
+the RSA code which is based on the PKCS \#1 standards.}. They are all based on established
number theory and cryptography.
\subsection{What the library IS NOT for?}
@@ -241,19 +242,20 @@ \section{Introduction}
if it failed. Certain functions that return int will return $-1$ to indicate an error. These functions will be explicitly
commented upon. When a function does return a CRYPT error code it can be translated into a string with
+\index{error\_to\_string()}
\begin{verbatim}
-const char *error_to_string(int errno);
+const char *error_to_string(int err);
\end{verbatim}
An example of handling an error is:
\begin{verbatim}
void somefunc(void)
{
- int errno;
+ int err;
/* call a cryptographic function */
- if ((errno = some_crypto_function(...)) != CRYPT_OK) {
- printf("A crypto error occured, %s\n", error_to_string(errno));
+ if ((err = some_crypto_function(...)) != CRYPT_OK) {
+ printf("A crypto error occured, %s\n", error_to_string(err));
/* perform error handling */
}
/* continue on if no error occured */
@@ -320,14 +322,14 @@ \section{Functions with Variable Length
rsa_key key;
unsigned char buffer[1024];
unsigned long x;
- int errno;
+ int err;
/* ... Make up the RSA key somehow */
/* lets export the key, set x to the size of the output buffer */
x = sizeof(buffer);
- if ((errno = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
- printf("Export error: %s\n", error_to_string(errno));
+ if ((err = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
+ printf("Export error: %s\n", error_to_string(err));
return -1;
}
@@ -411,12 +413,12 @@ \section{Core Functions}
#include <mycrypt.h>
int main(void)
{
- int keysize, errno;
+ int keysize, err;
/* now given a 20 byte key what keysize does Twofish want to use? */
keysize = 20;
- if ((errno = twofish_keysize(&keysize)) != CRYPT_OK) {
- printf("Error getting key size: %s\n", error_to_string(errno));
+ if ((err = twofish_keysize(&keysize)) != CRYPT_OK) {
+ printf("Error getting key size: %s\n", error_to_string(err));
return -1;
}
printf("Twofish suggested a key size of %d\n", keysize);
@@ -434,22 +436,30 @@ \section{Core Functions}
{
unsigned char pt[8], ct[8], key[8];
symmetric_key skey;
- int errno;
+ int err;
/* ... key is loaded appropriately in ``key'' ... */
/* ... load a block of plaintext in ``pt'' ... */
/* schedule the key */
- if ((errno = blowfish_setup(key, 8, 0, &skey)) != CRYPT_OK) {
- printf("Setup error: %s\n", error_to_string(errno));
+ if ((err = blowfish_setup(key, /* the key we will use */
+ 8, /* key is 8 bytes (64-bits) long */
+ 0, /* 0 == use default # of rounds */
+ &skey) /* where to put the scheduled key */
+ ) != CRYPT_OK) {
+ printf("Setup error: %s\n", error_to_string(err));
return -1;
}
/* encrypt the block */
- blowfish_ecb_encrypt(pt, ct, &skey);
+ blowfish_ecb_encrypt(pt, /* encrypt this 8-byte array */
+ ct, /* store encrypted data here */
+ &skey); /* our previously scheduled key */
/* decrypt the block */
- blowfish_ecb_decrypt(ct, pt, &skey);
+ blowfish_ecb_decrypt(ct, /* decrypt this 8-byte array */
+ pt, /* store decrypted data here */
+ &skey); /* our previously scheduled key */
return 0;
}
@@ -501,6 +511,7 @@ \section{The Cipher Descriptors}
As of this release the current cipher\_descriptors elements are
+\index{Cipher descriptor table}
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|}
@@ -516,6 +527,7 @@ \section{The Cipher Descriptors}
\hline Safer K128 & safer\_k128\_desc & 8 & 16 & 6 $\ldots$ 13 \\
\hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 $\ldots$ 13 \\
\hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\
+ & aes\_enc\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\
\hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\
\hline DES & des\_desc & 8 & 7 & 16 \\
\hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\
@@ -528,14 +540,32 @@ \subsection{Notes}
\end{small}
\subsection{Notes}
+\begin{small}
+\begin{enumerate}
+\item
+For AES (also known as Rijndael) there are four descriptors which complicate issues a little. The descriptors
+rijndael\_desc and rijndael\_enc\_desc provide the cipher named ``rijndael''. The descriptors aes\_desc and
+aes\_enc\_desc provide the cipher name ``aes''. Functionally both ``rijndael'' and ``aes'' are the same cipher. The
+only difference is when you call find\_cipher() you have to pass the correct name. The cipher descriptors with ``enc''
+in the middle (e.g. rijndael\_enc\_desc) are related to an implementation of Rijndael with only the encryption routine
+and tables. The decryption and self--test function pointers of both ``encrypt only'' descriptors are set to \textbf{NULL} and
+should not be called.
+
+The ``encrypt only'' descriptors are useful for applications that only use the encryption function of the cipher. Algorithms such
+as EAX, PMAC and OMAC only require the encryption function. So far this ``encrypt only'' functionality has only been implemented for
+Rijndael as it makes the most sense for this cipher.
+
+\item
For the 64-bit SAFER famliy of ciphers (e.g K64, SK64, K128, SK128) the ecb\_encrypt() and ecb\_decrypt()
functions are the same. So if you want to use those functions directly just call safer\_ecb\_encrypt()
or safer\_ecb\_decrypt() respectively.
+\item
Note that for ``DES'' and ``3DES'' they use 8 and 24 byte keys but only 7 and 21 [respectively] bytes of the keys are in
fact used for the purposes of encryption. My suggestion is just to use random 8/24 byte keys instead of trying to make a 8/24
byte string from the real 7/21 byte key.
+\item
Note that ``Twofish'' has additional configuration options that take place at build time. These options are found in
the file ``mycrypt\_cfg.h''. The first option is ``TWOFISH\_SMALL'' which when defined will force the Twofish code
to not pre-compute the Twofish ``$g(X)$'' function as a set of four $8 \times 32$ s-boxes. This means that a scheduled
@@ -545,6 +575,7 @@ \subsection{Notes}
speed increase is useful when ``TWOFISH\_SMALL'' is defined since the s-boxes and MDS multiply form the heart of the
Twofish round function.
+\index{Twofish build options}
\begin{small}
\begin{center}
\begin{tabular}{|l|l|l|}
@@ -558,7 +589,11 @@ \subsection{Notes}
\end{center}
\end{small}
+\end{enumerate}
+\end{small}
+
To work with the cipher\_descriptor array there is a function:
+\index{find\_cipher()}
\begin{verbatim}
int find_cipher(char *name)
\end{verbatim}
@@ -571,7 +606,7 @@ \subsection{Notes}
{
unsigned char key[8];
symmetric_key skey;
- int errno;
+ int err;
/* you must register a cipher before you use it */
if (register_cipher(&blowfish_desc)) == -1) {
@@ -580,8 +615,8 @@ \subsection{Notes}
}
/* generic call to function (assuming the key in key[] was already setup) */
- if ((errno = cipher_descriptor[find_cipher("blowfish")].setup(key, 8, 0, &skey)) != CRYPT_OK) {
- printf("Error setting up Blowfish: %s\n", error_to_string(errno));
+ if ((err = cipher_descriptor[find