Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cyassl-client Sync
Revision 0:5045d2638c29, committed 2011-02-05
- Comitter:
- toddouska
- Date:
- Sat Feb 05 01:09:17 2011 +0000
- Commit message:
- Beta Version
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/aes.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,1308 @@
+/* aes.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef NO_AES
+
+#include "ctc_aes.h"
+#ifdef NO_INLINE
+ #include "misc.h"
+#else
+ #include "misc.c"
+#endif
+
+
+static const word32 rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000,
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+
+static const word32 Te[5][256] = {
+{
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+},
+{
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+},
+{
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+},
+{
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+},
+{
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+}
+};
+
+
+static const word32 Td[5][256] = {
+{
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+},
+{
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+},
+{
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+},
+{
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+},
+{
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+}
+};
+
+
+
+#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y))))
+
+
+#ifdef CYASSL_AESNI
+
+#define cpuid(func,ax,bx,cx,dx)\
+ __asm__ __volatile__ ("cpuid":\
+ "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
+
+static int Check_CPU_support_AES()
+{
+ unsigned int a,b,c,d;
+ cpuid(1,a,b,c,d);
+
+ if (c & 0x2000000)
+ return 1;
+
+ return 0;
+}
+
+static int checkAESNI = 0;
+static int haveAESNI = 0;
+
+
+void AES_CBC_encrypt(const unsigned char* in, unsigned char* out,
+ unsigned char* ivec, unsigned long length,
+ const unsigned char* KS, int nr);
+
+
+void AES_CBC_decrypt(const unsigned char* in, unsigned char* out,
+ unsigned char* ivec, unsigned long length,
+ const unsigned char* KS, int nr);
+
+void AES_128_Key_Expansion(const unsigned char* userkey,
+ unsigned char* key_schedule);
+
+void AES_192_Key_Expansion(const unsigned char* userkey,
+ unsigned char* key_schedule);
+
+void AES_256_Key_Expansion(const unsigned char* userkey,
+ unsigned char* key_schedule);
+
+
+int AES_set_encrypt_key (const unsigned char *userKey, const int bits,
+ Aes* aes)
+{
+ if (!userKey || !aes)
+ return -1;
+
+ if (bits == 128) {
+ AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10;
+ return 0;
+ }
+ else if (bits == 192) {
+ AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12;
+ return 0;
+ }
+ else if (bits == 256) {
+ AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14;
+ return 0;
+ }
+ return -1;
+}
+
+
+int AES_set_decrypt_key (const unsigned char* userKey, const int bits,
+ Aes* aes)
+{
+ int nr;
+ Aes temp_key;
+ __m128i *Key_Schedule = (__m128i*)aes->key;
+ __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key;
+
+ if (!userKey || !aes)
+ return -1;
+
+ if (AES_set_encrypt_key(userKey,bits,&temp_key) == -1)
+ return -1;
+
+ nr = temp_key.rounds;
+ aes->rounds = nr;
+
+ Key_Schedule[nr] = Temp_Key_Schedule[0];
+ Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]);
+ Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]);
+ Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]);
+ Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]);
+ Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]);
+ Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]);
+ Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]);
+ Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]);
+ Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]);
+
+ if(nr>10) {
+ Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]);
+ Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]);
+ }
+
+ if(nr>12) {
+ Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]);
+ Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]);
+ }
+
+ Key_Schedule[0] = Temp_Key_Schedule[nr];
+
+ return 0;
+}
+
+
+
+#endif /* CYASSL_AESNI */
+
+
+int AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv,
+ int dir)
+{
+ word32 temp, *rk = aes->key;
+ unsigned int i = 0;
+
+ if (!((keylen == 16) || (keylen == 24) || (keylen == 32)))
+ return -1;
+
+#ifdef CYASSL_AESNI
+ if (checkAESNI == 0) {
+ haveAESNI = Check_CPU_support_AES();
+ checkAESNI = 1;
+ }
+ if (haveAESNI) {
+ XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
+ if (dir == AES_ENCRYPTION)
+ return AES_set_encrypt_key(userKey, keylen * 8, aes);
+ else
+ return AES_set_decrypt_key(userKey, keylen * 8, aes);
+ }
+#endif /* CYASSL_AESNI */
+
+ aes->rounds = keylen/4 + 6;
+
+ XMEMCPY(rk, userKey, keylen);
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseWords(rk, rk, keylen);
+ #endif
+
+ switch(keylen)
+ {
+ case 16:
+ while (1)
+ {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10)
+ break;
+ rk += 4;
+ }
+ break;
+
+ case 24:
+ while (1) /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */
+ {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
+ (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8)
+ break;
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ break;
+
+ case 32:
+ while (1)
+ {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te[4][GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te[4][GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7)
+ break;
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te[4][GETBYTE(temp, 3)] & 0xff000000) ^
+ (Te[4][GETBYTE(temp, 2)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(temp, 1)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(temp, 0)] & 0x000000ff);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+
+ rk += 8;
+ }
+ break;
+ }
+
+ if (dir == AES_DECRYPTION)
+ {
+ unsigned int i, j;
+ rk = aes->key;
+
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4* aes->rounds; i < j; i += 4, j -= 4) {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ /* apply the inverse MixColumn transform to all round keys but the
+ first and the last: */
+ for (i = 1; i < aes->rounds; i++) {
+ rk += 4;
+ rk[0] =
+ Td[0][Te[4][GETBYTE(rk[0], 3)] & 0xff] ^
+ Td[1][Te[4][GETBYTE(rk[0], 2)] & 0xff] ^
+ Td[2][Te[4][GETBYTE(rk[0], 1)] & 0xff] ^
+ Td[3][Te[4][GETBYTE(rk[0], 0)] & 0xff];
+ rk[1] =
+ Td[0][Te[4][GETBYTE(rk[1], 3)] & 0xff] ^
+ Td[1][Te[4][GETBYTE(rk[1], 2)] & 0xff] ^
+ Td[2][Te[4][GETBYTE(rk[1], 1)] & 0xff] ^
+ Td[3][Te[4][GETBYTE(rk[1], 0)] & 0xff];
+ rk[2] =
+ Td[0][Te[4][GETBYTE(rk[2], 3)] & 0xff] ^
+ Td[1][Te[4][GETBYTE(rk[2], 2)] & 0xff] ^
+ Td[2][Te[4][GETBYTE(rk[2], 1)] & 0xff] ^
+ Td[3][Te[4][GETBYTE(rk[2], 0)] & 0xff];
+ rk[3] =
+ Td[0][Te[4][GETBYTE(rk[3], 3)] & 0xff] ^
+ Td[1][Te[4][GETBYTE(rk[3], 2)] & 0xff] ^
+ Td[2][Te[4][GETBYTE(rk[3], 1)] & 0xff] ^
+ Td[3][Te[4][GETBYTE(rk[3], 0)] & 0xff];
+ }
+ }
+ XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE);
+
+ return 0;
+}
+
+
+void AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+{
+ word32 s0, s1, s2, s3;
+ word32 t0, t1, t2, t3;
+ word32 r = aes->rounds >> 1;
+
+ const word32* rk = aes->key;
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ XMEMCPY(&s0, inBlock, sizeof(s0));
+ XMEMCPY(&s1, inBlock + sizeof(s0), sizeof(s1));
+ XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));
+ XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));
+
+ #ifdef LITTLE_ENDIAN_ORDER
+ s0 = ByteReverseWord32(s0);
+ s1 = ByteReverseWord32(s1);
+ s2 = ByteReverseWord32(s2);
+ s3 = ByteReverseWord32(s3);
+ #endif
+
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+
+ /*
+ * Nr - 1 full rounds:
+ */
+
+ for (;;) {
+ t0 =
+ Te[0][GETBYTE(s0, 3)] ^
+ Te[1][GETBYTE(s1, 2)] ^
+ Te[2][GETBYTE(s2, 1)] ^
+ Te[3][GETBYTE(s3, 0)] ^
+ rk[4];
+ t1 =
+ Te[0][GETBYTE(s1, 3)] ^
+ Te[1][GETBYTE(s2, 2)] ^
+ Te[2][GETBYTE(s3, 1)] ^
+ Te[3][GETBYTE(s0, 0)] ^
+ rk[5];
+ t2 =
+ Te[0][GETBYTE(s2, 3)] ^
+ Te[1][GETBYTE(s3, 2)] ^
+ Te[2][GETBYTE(s0, 1)] ^
+ Te[3][GETBYTE(s1, 0)] ^
+ rk[6];
+ t3 =
+ Te[0][GETBYTE(s3, 3)] ^
+ Te[1][GETBYTE(s0, 2)] ^
+ Te[2][GETBYTE(s1, 1)] ^
+ Te[3][GETBYTE(s2, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Te[0][GETBYTE(t0, 3)] ^
+ Te[1][GETBYTE(t1, 2)] ^
+ Te[2][GETBYTE(t2, 1)] ^
+ Te[3][GETBYTE(t3, 0)] ^
+ rk[0];
+ s1 =
+ Te[0][GETBYTE(t1, 3)] ^
+ Te[1][GETBYTE(t2, 2)] ^
+ Te[2][GETBYTE(t3, 1)] ^
+ Te[3][GETBYTE(t0, 0)] ^
+ rk[1];
+ s2 =
+ Te[0][GETBYTE(t2, 3)] ^
+ Te[1][GETBYTE(t3, 2)] ^
+ Te[2][GETBYTE(t0, 1)] ^
+ Te[3][GETBYTE(t1, 0)] ^
+ rk[2];
+ s3 =
+ Te[0][GETBYTE(t3, 3)] ^
+ Te[1][GETBYTE(t0, 2)] ^
+ Te[2][GETBYTE(t1, 1)] ^
+ Te[3][GETBYTE(t2, 0)] ^
+ rk[3];
+ }
+
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+
+ s0 =
+ (Te[4][GETBYTE(t0, 3)] & 0xff000000) ^
+ (Te[4][GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Te[4][GETBYTE(t1, 3)] & 0xff000000) ^
+ (Te[4][GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Te[4][GETBYTE(t2, 3)] & 0xff000000) ^
+ (Te[4][GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Te[4][GETBYTE(t3, 3)] & 0xff000000) ^
+ (Te[4][GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Te[4][GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Te[4][GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[3];
+
+ /* write out */
+ #ifdef LITTLE_ENDIAN_ORDER
+ s0 = ByteReverseWord32(s0);
+ s1 = ByteReverseWord32(s1);
+ s2 = ByteReverseWord32(s2);
+ s3 = ByteReverseWord32(s3);
+ #endif
+
+ XMEMCPY(outBlock, &s0, sizeof(s0));
+ XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1));
+ XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));
+ XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));
+}
+
+
+void AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock)
+{
+ word32 s0, s1, s2, s3;
+ word32 t0, t1, t2, t3;
+ word32 r = aes->rounds >> 1;
+
+ const word32* rk = aes->key;
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ XMEMCPY(&s0, inBlock, sizeof(s0));
+ XMEMCPY(&s1, inBlock + sizeof(s0), sizeof(s1));
+ XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2));
+ XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3));
+
+ #ifdef LITTLE_ENDIAN_ORDER
+ s0 = ByteReverseWord32(s0);
+ s1 = ByteReverseWord32(s1);
+ s2 = ByteReverseWord32(s2);
+ s3 = ByteReverseWord32(s3);
+ #endif
+
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+
+ /*
+ * Nr - 1 full rounds:
+ */
+
+ for (;;) {
+ t0 =
+ Td[0][GETBYTE(s0, 3)] ^
+ Td[1][GETBYTE(s3, 2)] ^
+ Td[2][GETBYTE(s2, 1)] ^
+ Td[3][GETBYTE(s1, 0)] ^
+ rk[4];
+ t1 =
+ Td[0][GETBYTE(s1, 3)] ^
+ Td[1][GETBYTE(s0, 2)] ^
+ Td[2][GETBYTE(s3, 1)] ^
+ Td[3][GETBYTE(s2, 0)] ^
+ rk[5];
+ t2 =
+ Td[0][GETBYTE(s2, 3)] ^
+ Td[1][GETBYTE(s1, 2)] ^
+ Td[2][GETBYTE(s0, 1)] ^
+ Td[3][GETBYTE(s3, 0)] ^
+ rk[6];
+ t3 =
+ Td[0][GETBYTE(s3, 3)] ^
+ Td[1][GETBYTE(s2, 2)] ^
+ Td[2][GETBYTE(s1, 1)] ^
+ Td[3][GETBYTE(s0, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Td[0][GETBYTE(t0, 3)] ^
+ Td[1][GETBYTE(t3, 2)] ^
+ Td[2][GETBYTE(t2, 1)] ^
+ Td[3][GETBYTE(t1, 0)] ^
+ rk[0];
+ s1 =
+ Td[0][GETBYTE(t1, 3)] ^
+ Td[1][GETBYTE(t0, 2)] ^
+ Td[2][GETBYTE(t3, 1)] ^
+ Td[3][GETBYTE(t2, 0)] ^
+ rk[1];
+ s2 =
+ Td[0][GETBYTE(t2, 3)] ^
+ Td[1][GETBYTE(t1, 2)] ^
+ Td[2][GETBYTE(t0, 1)] ^
+ Td[3][GETBYTE(t3, 0)] ^
+ rk[2];
+ s3 =
+ Td[0][GETBYTE(t3, 3)] ^
+ Td[1][GETBYTE(t2, 2)] ^
+ Td[2][GETBYTE(t1, 1)] ^
+ Td[3][GETBYTE(t0, 0)] ^
+ rk[3];
+ }
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td[4][GETBYTE(t0, 3)] & 0xff000000) ^
+ (Td[4][GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Td[4][GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Td[4][GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Td[4][GETBYTE(t1, 3)] & 0xff000000) ^
+ (Td[4][GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Td[4][GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Td[4][GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Td[4][GETBYTE(t2, 3)] & 0xff000000) ^
+ (Td[4][GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Td[4][GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Td[4][GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Td[4][GETBYTE(t3, 3)] & 0xff000000) ^
+ (Td[4][GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Td[4][GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Td[4][GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[3];
+
+ /* write out */
+ #ifdef LITTLE_ENDIAN_ORDER
+ s0 = ByteReverseWord32(s0);
+ s1 = ByteReverseWord32(s1);
+ s2 = ByteReverseWord32(s2);
+ s3 = ByteReverseWord32(s3);
+ #endif
+
+ XMEMCPY(outBlock, &s0, sizeof(s0));
+ XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1));
+ XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2));
+ XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3));
+}
+
+
+void AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / AES_BLOCK_SIZE;
+
+#ifdef CYASSL_AESNI
+ if (haveAESNI) {
+ #ifdef DEBUG_AESNI
+ printf("about to aes cbc encrypt\n");
+ printf("in = %p\n", in);
+ printf("out = %p\n", out);
+ printf("aes->key = %p\n", aes->key);
+ printf("aes->reg = %p\n", aes->reg);
+ printf("aes->rounds = %d\n", aes->rounds);
+ printf("sz = %d\n", sz);
+ #endif
+ AES_CBC_encrypt(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
+ aes->rounds);
+ /* store iv for next call */
+ XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ return;
+ }
+#endif
+
+ while (blocks--) {
+ xorbuf((byte*)aes->reg, in, AES_BLOCK_SIZE);
+ AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->reg);
+ XMEMCPY(out, aes->reg, AES_BLOCK_SIZE);
+
+ out += AES_BLOCK_SIZE;
+ in += AES_BLOCK_SIZE;
+ }
+}
+
+
+void AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / AES_BLOCK_SIZE;
+
+#ifdef CYASSL_AESNI
+ if (haveAESNI) {
+ #ifdef DEBUG_AESNI
+ printf("about to aes cbc decrypt\n");
+ printf("in = %p\n", in);
+ printf("out = %p\n", out);
+ printf("aes->key = %p\n", aes->key);
+ printf("aes->reg = %p\n", aes->reg);
+ printf("aes->rounds = %d\n", aes->rounds);
+ printf("sz = %d\n", sz);
+ #endif
+
+ /* if input and output same will overwirte input iv */
+ XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ AES_CBC_decrypt(in, out, (byte*)aes->reg, sz, (byte*)aes->key,
+ aes->rounds);
+ /* store iv for next call */
+ XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+ return;
+ }
+#endif
+
+ while (blocks--) {
+ XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE);
+ AesDecrypt(aes, (byte*)aes->tmp, out);
+ xorbuf(out, (byte*)aes->reg, AES_BLOCK_SIZE);
+ XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
+
+ out += AES_BLOCK_SIZE;
+ in += AES_BLOCK_SIZE;
+ }
+}
+
+
+#endif /* NO_AES */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arc4.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,76 @@
+/* arc4.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "arc4.h"
+
+
+
+void Arc4SetKey(Arc4* arc4, const byte* key, word32 length)
+{
+ word32 i;
+ word32 keyIndex = 0, stateIndex = 0;
+
+ arc4->x = 1;
+ arc4->y = 0;
+
+ for (i = 0; i < ARC4_STATE_SIZE; i++)
+ arc4->state[i] = i;
+
+ for (i = 0; i < ARC4_STATE_SIZE; i++) {
+ word32 a = arc4->state[i];
+ stateIndex += key[keyIndex] + a;
+ stateIndex &= 0xFF;
+ arc4->state[i] = arc4->state[stateIndex];
+ arc4->state[stateIndex] = a;
+
+ if (++keyIndex >= length)
+ keyIndex = 0;
+ }
+}
+
+
+static INLINE word32 MakeByte(word32* x, word32* y, byte* s)
+{
+ word32 a = s[*x], b;
+ *y = (*y+a) & 0xff;
+
+ b = s[*y];
+ s[*x] = b;
+ s[*y] = a;
+ *x = (*x+1) & 0xff;
+
+ return s[(a+b) & 0xff];
+}
+
+
+void Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length)
+{
+ word32 x = arc4->x;
+ word32 y = arc4->y;
+
+ while(length--)
+ *out++ = *in++ ^ MakeByte(&x, &y, arc4->state);
+
+ arc4->x = x;
+ arc4->y = y;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/arc4.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,56 @@
+/* arc4.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_ARC4_H
+#define CTAO_CRYPT_ARC4_H
+
+
+#include "types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+enum {
+ ARC4_STATE_SIZE = 256
+};
+
+/* ARC4 encryption and decryption */
+typedef struct Arc4 {
+ byte x;
+ byte y;
+ byte state[ARC4_STATE_SIZE];
+} Arc4;
+
+void Arc4Process(Arc4*, byte*, const byte*, word32);
+void Arc4SetKey(Arc4*, const byte*, word32);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* CTAO_CRYPT_ARC4_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/asn.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,2648 @@
+/* asn.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifdef THREADX
+ #include "os.h" /* dc_rtc_api needs */
+ #include "dc_rtc_api.h" /* to get current time */
+#endif
+#include "asn.h"
+#include "coding.h"
+#include "ctc_sha.h"
+#include "ctc_md5.h"
+#include "error.h"
+
+#ifdef HAVE_NTRU
+ #include "crypto_ntru.h"
+#endif
+
+
+#ifdef _MSC_VER
+ /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
+ #pragma warning(disable: 4996)
+#endif
+
+
+#ifndef TRUE
+enum {
+ FALSE = 0,
+ TRUE = 1
+};
+#endif
+
+enum {
+ ISSUER = 0,
+ SUBJECT = 1,
+
+ BEFORE = 0,
+ AFTER = 1
+};
+
+
+#ifdef THREADX
+ /* uses parital <time.h> structures */
+ #define XTIME(tl) (0)
+ #define XGMTIME(c) my_gmtime((c))
+ #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
+#elif defined(MICRIUM)
+ #include <clk.h>
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ #define XVALIDATE_DATE(d, f, t) NetSecure_ValidDate((d), (f), (t))
+ #else
+ #define XVALIDATE_DATE(d, f, t) (0)
+ #endif
+ #define NO_TIME_H
+ /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */
+#elif defined(USER_TIME)
+ /* no <time.h> strucutres used */
+ #define NO_TIME_H
+ /* user time, and gmtime compatible functions, there is a gmtime
+ implementation here that WINCE uses, so really just need some ticks
+ since the EPOCH
+ */
+#else
+ /* default */
+ /* uses complete <time.h> facility */
+ #include <time.h>
+ #define XTIME(tl) time((tl))
+ #define XGMTIME(c) gmtime((c))
+ #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
+#endif
+
+
+#ifdef _WIN32_WCE
+/* no time() or gmtime() even though in time.h header?? */
+
+#include <windows.h>
+
+
+time_t time(time_t* timer)
+{
+ SYSTEMTIME sysTime;
+ FILETIME fTime;
+ ULARGE_INTEGER intTime;
+ time_t localTime;
+
+ if (timer == NULL)
+ timer = &localTime;
+
+ GetSystemTime(&sysTime);
+ SystemTimeToFileTime(&sysTime, &fTime);
+
+ XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
+ /* subtract EPOCH */
+ intTime.QuadPart -= 0x19db1ded53e8000;
+ /* to secs */
+ intTime.QuadPart /= 10000000;
+ *timer = (time_t)intTime.QuadPart;
+
+ return *timer;
+}
+
+
+
+struct tm* gmtime(const time_t* timer)
+{
+ #define YEAR0 1900
+ #define EPOCH_YEAR 1970
+ #define SECS_DAY (24L * 60L * 60L)
+ #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
+ #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
+
+ static const int _ytab[2][12] =
+ {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+ };
+
+ static struct tm st_time;
+ struct tm* ret = &st_time;
+ time_t time = *timer;
+ unsigned long dayclock, dayno;
+ int year = EPOCH_YEAR;
+
+ dayclock = (unsigned long)time % SECS_DAY;
+ dayno = (unsigned long)time / SECS_DAY;
+
+ ret->tm_sec = dayclock % 60;
+ ret->tm_min = (dayclock % 3600) / 60;
+ ret->tm_hour = dayclock / 3600;
+ ret->tm_wday = (dayno + 4) % 7; /* day 0 a Thursday */
+
+ while(dayno >= (unsigned long)YEARSIZE(year)) {
+ dayno -= YEARSIZE(year);
+ year++;
+ }
+
+ ret->tm_year = year - YEAR0;
+ ret->tm_yday = dayno;
+ ret->tm_mon = 0;
+
+ while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
+ dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
+ ret->tm_mon++;
+ }
+
+ ret->tm_mday = ++dayno;
+ ret->tm_isdst = 0;
+
+ return ret;
+}
+
+#endif /* _WIN32_WCE */
+
+
+
+#ifdef THREADX
+
+#define YEAR0 1900
+
+struct tm* my_gmtime(const time_t* timer) /* has a gmtime() but hangs */
+{
+ static struct tm st_time;
+ struct tm* ret = &st_time;
+
+ DC_RTC_CALENDAR cal;
+ dc_rtc_time_get(&cal, TRUE);
+
+ ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */
+ ret->tm_mon = cal.month - 1; /* gm starts at 0 */
+ ret->tm_mday = cal.day;
+ ret->tm_hour = cal.hour;
+ ret->tm_min = cal.minute;
+ ret->tm_sec = cal.second;
+
+ return ret;
+}
+
+#endif /* THREADX */
+
+
+static INLINE word32 btoi(byte b)
+{
+ return b - 0x30;
+}
+
+
+/* two byte date/time, add to value */
+static INLINE void GetTime(int* value, const byte* date, int* idx)
+{
+ int i = *idx;
+
+ *value += btoi(date[i++]) * 10;
+ *value += btoi(date[i++]);
+
+ *idx = i;
+}
+
+
+#if defined(MICRIUM)
+
+static int NetSecure_ValidDate(CPU_INT08U *date, CPU_INT08U format,
+ CPU_INT08U dateType)
+{
+ CLK_DATE_TIME cert_date_time;
+ CLK_TS_SEC cert_ts_sec;
+ CLK_TS_SEC local_ts_sec;
+ CPU_INT32S i;
+ CPU_INT32S val;
+
+ local_ts_sec = Clk_GetTS();
+ XMEMSET(&cert_date_time, 0, sizeof(cert_date_time));
+
+ i = 0;
+ if (format == ASN_UTC_TIME) {
+ if (btoi(date[0]) >= 5)
+ cert_date_time.Yr = 1900;
+ else
+ cert_date_time.Yr = 2000;
+ }
+ else { /* format == GENERALIZED_TIME */
+ cert_date_time.Yr += btoi(date[i++]) * 1000;
+ cert_date_time.Yr += btoi(date[i++]) * 100;
+ }
+
+ val = cert_date_time.Yr;
+ GetTime(&val, date, &i);
+ cert_date_time.Yr = (CLK_YR)val;
+
+ val = 0;
+ GetTime(&val, date, &i);
+ cert_date_time.Month = (CLK_MONTH)val;
+
+ val = 0;
+ GetTime(&val, date, &i);
+ cert_date_time.Day = (CLK_DAY)val;
+
+ val = 0;
+ GetTime(&val, date, &i);
+ cert_date_time.Hr = (CLK_HR)val;
+
+ val = 0;
+ GetTime(&val, date, &i);
+ cert_date_time.Min = (CLK_MIN)val;
+
+ val = 0;
+ GetTime(&val, date, &i);
+ cert_date_time.Sec = (CLK_SEC)val;
+
+ if (date[i] != 'Z') /* only Zulu supported for this profile */
+ return 0;
+
+ cert_date_time.DayOfWk = 1;
+ cert_date_time.DayOfYr = 1;
+ Clk_DateTimeToTS(&cert_ts_sec, &cert_date_time);
+
+
+ if (dateType == BEFORE) {
+ if (local_ts_sec < cert_ts_sec) /* If cert creation date after
+ current date... */
+ return (DEF_FAIL); /* ... report an error. */
+ } else {
+ if (local_ts_sec > cert_ts_sec) /* If cert expiration date before
+ current date... */
+ return (DEF_FAIL); /* ... report an error. */
+ }
+
+ return (DEF_OK);
+}
+
+#endif /* MICRIUM */
+
+
+int GetLength(const byte* input, word32* inOutIdx, int* len)
+{
+ int length = 0;
+ word32 i = *inOutIdx;
+
+ byte b = input[i++];
+ if (b >= ASN_LONG_LENGTH) {
+ word32 bytes = b & 0x7F;
+
+ while (bytes--) {
+ b = input[i++];
+ length = (length << 8) | b;
+ }
+ }
+ else
+ length = b;
+
+ *inOutIdx = i;
+ *len = length;
+
+ return length;
+}
+
+
+int GetSequence(const byte* input, word32* inOutIdx, int* len)
+{
+ int length = -1;
+ word32 idx = *inOutIdx;
+
+ if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
+ GetLength(input, &idx, &length) < 0)
+ return ASN_PARSE_E;
+
+ *len = length;
+ *inOutIdx = idx;
+
+ return length;
+}
+
+
+int GetSet(const byte* input, word32* inOutIdx, int* len)
+{
+ int length = -1;
+ word32 idx = *inOutIdx;
+
+ if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) ||
+ GetLength(input, &idx, &length) < 0)
+ return ASN_PARSE_E;
+
+ *len = length;
+ *inOutIdx = idx;
+
+ return length;
+}
+
+
+/* winodws header clash for WinCE using GetVersion */
+int GetMyVersion(const byte* input, word32* inOutIdx, int* version)
+{
+ word32 idx = *inOutIdx;
+
+ if (input[idx++] != ASN_INTEGER)
+ return ASN_PARSE_E;
+
+ if (input[idx++] != 0x01)
+ return ASN_VERSION_E;
+
+ *version = input[idx++];
+ *inOutIdx = idx;
+
+ return *version;
+}
+
+
+/* May not have one, not an error */
+int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
+{
+ word32 idx = *inOutIdx;
+
+ if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+ *inOutIdx = ++idx; /* eat header */
+ return GetMyVersion(input, inOutIdx, version);
+ }
+
+ /* go back as is */
+ *version = 0;
+
+ return 0;
+}
+
+
+int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx )
+{
+ word32 i = *inOutIdx;
+ byte b = input[i++];
+ int length;
+
+ if (b != ASN_INTEGER)
+ return ASN_PARSE_E;
+
+ if (GetLength(input, &i, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ( (b = input[i++]) == 0x00)
+ length--;
+ else
+ i--;
+
+ mp_init(mpi);
+ if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) {
+ mp_clear(mpi);
+ return ASN_GETINT_E;
+ }
+
+ *inOutIdx = i + length;
+ return 0;
+}
+
+
+static int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid)
+{
+ int length;
+ word32 i = *inOutIdx;
+ byte b;
+ *oid = 0;
+
+ if (GetSequence(input, &i, &length) < 0)
+ return ASN_PARSE_E;
+
+ b = input[i++];
+ if (b != ASN_OBJECT_ID)
+ return ASN_OBJECT_ID_E;
+
+ if (GetLength(input, &i, &length) < 0)
+ return ASN_PARSE_E;
+
+ while(length--)
+ *oid += input[i++];
+ /* just sum it up for now */
+
+ /* could have NULL tag and 0 terminator, but may not */
+ b = input[i++];
+
+ if (b == ASN_TAG_NULL) {
+ b = input[i++];
+ if (b != 0)
+ return ASN_EXPECT_0_E;
+ }
+ else
+ /* go back, didn't have it */
+ i--;
+
+ *inOutIdx = i;
+
+ return 0;
+}
+
+
+int RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+ word32 inSz)
+{
+ word32 begin = *inOutIdx;
+ int version, length;
+
+ if (GetSequence(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)length > (inSz - (*inOutIdx - begin)))
+ return ASN_INPUT_E;
+
+ if (GetMyVersion(input, inOutIdx, &version) < 0)
+ return ASN_PARSE_E;
+
+ key->type = RSA_PRIVATE;
+
+ if (GetInt(&key->n, input, inOutIdx) < 0 ||
+ GetInt(&key->e, input, inOutIdx) < 0 ||
+ GetInt(&key->d, input, inOutIdx) < 0 ||
+ GetInt(&key->p, input, inOutIdx) < 0 ||
+ GetInt(&key->q, input, inOutIdx) < 0 ||
+ GetInt(&key->dP, input, inOutIdx) < 0 ||
+ GetInt(&key->dQ, input, inOutIdx) < 0 ||
+ GetInt(&key->u, input, inOutIdx) < 0 ) return ASN_RSA_KEY_E;
+
+ return 0;
+}
+
+
+/* Remove PKCS8 header, move beginning of traditional to beginning of input */
+int ToTraditional(byte* input, word32 sz)
+{
+ word32 inOutIdx = 0, oid;
+ int version, length;
+
+ if (GetSequence(input, &inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)length > (sz - inOutIdx))
+ return ASN_INPUT_E;
+
+ if (GetMyVersion(input, &inOutIdx, &version) < 0)
+ return ASN_PARSE_E;
+
+ if (GetAlgoId(input, &inOutIdx, &oid) < 0)
+ return ASN_PARSE_E;
+
+ if (input[inOutIdx++] != ASN_OCTET_STRING)
+ return ASN_PARSE_E;
+
+ if (GetLength(input, &inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)length > (sz - inOutIdx))
+ return ASN_INPUT_E;
+
+ XMEMMOVE(input, input + inOutIdx, length);
+
+ return 0;
+}
+
+
+int RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+ word32 inSz)
+{
+ word32 begin = *inOutIdx;
+ int length;
+ byte b;
+
+ if (GetSequence(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)length > (inSz - (*inOutIdx - begin)))
+ return ASN_INPUT_E;
+
+ key->type = RSA_PUBLIC;
+ b = input[*inOutIdx];
+
+#ifdef OPENSSL_EXTRA
+ if (b != ASN_INTEGER) {
+ /* not from decoded cert, will have algo id, skip past */
+ if (GetSequence(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ b = input[(*inOutIdx)++];
+ if (b != ASN_OBJECT_ID)
+ return ASN_OBJECT_ID_E;
+
+ if (GetLength(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ *inOutIdx += length; /* skip past */
+
+ /* could have NULL tag and 0 terminator, but may not */
+ b = input[(*inOutIdx)++];
+
+ if (b == ASN_TAG_NULL) {
+ b = input[(*inOutIdx)++];
+ if (b != 0)
+ return ASN_EXPECT_0_E;
+ }
+ else
+ /* go back, didn't have it */
+ (*inOutIdx)--;
+
+ /* should have bit tag length and seq next */
+ b = input[(*inOutIdx)++];
+ if (b != ASN_BIT_STRING)
+ return ASN_BITSTR_E;
+
+ if (GetLength(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ /* could have 0 */
+ b = input[(*inOutIdx)++];
+ if (b != 0)
+ (*inOutIdx)--;
+
+ if (GetSequence(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+ }
+#endif /* OPENSSL_EXTRA */
+
+ if (GetInt(&key->n, input, inOutIdx) < 0 ||
+ GetInt(&key->e, input, inOutIdx) < 0 ) return ASN_RSA_KEY_E;
+
+ return 0;
+}
+
+
+#ifndef NO_DH
+
+int DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
+{
+ word32 begin = *inOutIdx;
+ int length;
+
+ if (GetSequence(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)length > (inSz - (*inOutIdx - begin)))
+ return ASN_INPUT_E;
+
+ if (GetInt(&key->p, input, inOutIdx) < 0 ||
+ GetInt(&key->g, input, inOutIdx) < 0 ) return ASN_DH_KEY_E;
+
+ return 0;
+}
+
+int DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz)
+{
+ /* may have leading 0 */
+ if (p[0] == 0) {
+ pSz--; p++;
+ }
+
+ if (g[0] == 0) {
+ gSz--; g++;
+ }
+
+ mp_init(&key->p);
+ if (mp_read_unsigned_bin(&key->p, p, pSz) != 0) {
+ mp_clear(&key->p);
+ return ASN_DH_KEY_E;
+ }
+
+ mp_init(&key->g);
+ if (mp_read_unsigned_bin(&key->g, g, gSz) != 0) {
+ mp_clear(&key->p);
+ return ASN_DH_KEY_E;
+ }
+
+ return 0;
+}
+
+
+#endif /* NO_DH */
+
+
+#ifndef NO_DSA
+
+int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
+ word32 inSz)
+{
+ word32 begin = *inOutIdx;
+ int length;
+
+ if (GetSequence(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)length > (inSz - (*inOutIdx - begin)))
+ return ASN_INPUT_E;
+
+ if (GetInt(&key->p, input, inOutIdx) < 0 ||
+ GetInt(&key->q, input, inOutIdx) < 0 ||
+ GetInt(&key->g, input, inOutIdx) < 0 ||
+ GetInt(&key->y, input, inOutIdx) < 0 ) return ASN_DH_KEY_E;
+
+ key->type = DSA_PUBLIC;
+ return 0;
+}
+
+
+int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
+ word32 inSz)
+{
+ word32 begin = *inOutIdx;
+ int length, version;
+
+ if (GetSequence(input, inOutIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)length > (inSz - (*inOutIdx - begin)))
+ return ASN_INPUT_E;
+
+ if (GetMyVersion(input, inOutIdx, &version) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->p, input, inOutIdx) < 0 ||
+ GetInt(&key->q, input, inOutIdx) < 0 ||
+ GetInt(&key->g, input, inOutIdx) < 0 ||
+ GetInt(&key->y, input, inOutIdx) < 0 ||
+ GetInt(&key->x, input, inOutIdx) < 0 ) return ASN_DH_KEY_E;
+
+ key->type = DSA_PRIVATE;
+ return 0;
+}
+
+#endif /* NO_DSA */
+
+
+void InitDecodedCert(DecodedCert* cert, byte* source, void* heap)
+{
+ cert->publicKey = 0;
+ cert->pubKeyStored = 0;
+ cert->signature = 0;
+ cert->subjectCN = 0;
+ cert->subjectCNLen = 0;
+ cert->source = source; /* don't own */
+ cert->srcIdx = 0;
+ cert->heap = heap;
+#ifdef CYASSL_CERT_GEN
+ cert->subjectSN = 0;
+ cert->subjectSNLen = 0;
+ cert->subjectC = 0;
+ cert->subjectCLen = 0;
+ cert->subjectL = 0;
+ cert->subjectLLen = 0;
+ cert->subjectST = 0;
+ cert->subjectSTLen = 0;
+ cert->subjectO = 0;
+ cert->subjectOLen = 0;
+ cert->subjectOU = 0;
+ cert->subjectOULen = 0;
+ cert->subjectEmail = 0;
+ cert->subjectEmailLen = 0;
+#endif /* CYASSL_CERT_GEN */
+}
+
+
+void FreeDecodedCert(DecodedCert* cert)
+{
+ if (cert->subjectCNLen == 0) /* 0 means no longer pointer to raw, we own */
+ XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
+ if (cert->pubKeyStored == 1)
+ XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+}
+
+
+static int GetCertHeader(DecodedCert* cert, word32 inSz)
+{
+ int ret = 0, version, len;
+ word32 begin = cert->srcIdx;
+ mp_int mpi;
+
+ if (GetSequence(cert->source, &cert->srcIdx, &len) < 0)
+ return ASN_PARSE_E;
+
+ if ((word32)len > (inSz - (cert->srcIdx - begin))) return ASN_INPUT_E;
+
+ cert->certBegin = cert->srcIdx;
+
+ GetSequence(cert->source, &cert->srcIdx, &len);
+ cert->sigIndex = len + cert->srcIdx;
+
+ if (GetExplicitVersion(cert->source, &cert->srcIdx, &version) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&mpi, cert->source, &cert->srcIdx) < 0)
+ ret = ASN_PARSE_E;
+
+ mp_clear(&mpi);
+ return ret;
+}
+
+
+static int StoreKey(DecodedCert* cert)
+{
+ int length;
+ word32 read = cert->srcIdx;
+
+ if (cert->keyOID == NTRUk)
+ return 0; /* already stored */
+
+ if (GetSequence(cert->source, &cert->srcIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ read = cert->srcIdx - read;
+ length += read;
+
+ while (read--)
+ cert->srcIdx--;
+
+ cert->pubKeySize = length;
+ cert->publicKey = cert->source + cert->srcIdx;
+ cert->srcIdx += length;
+
+ return 0;
+}
+
+
+static int GetKey(DecodedCert* cert)
+{
+ int length;
+#ifdef HAVE_NTRU
+ int tmpIdx = cert->srcIdx;
+#endif
+
+ if (GetSequence(cert->source, &cert->srcIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID) < 0)
+ return ASN_PARSE_E;
+
+ if (cert->keyOID == RSAk) {
+ byte b = cert->source[cert->srcIdx++];
+ if (b != ASN_BIT_STRING)
+ return ASN_BITSTR_E;
+
+ if (GetLength(cert->source, &cert->srcIdx, &length) < 0)
+ return ASN_PARSE_E;
+ b = cert->source[cert->srcIdx++];
+ if (b != 0x00)
+ return ASN_EXPECT_0_E;
+ }
+ else if (cert->keyOID == DSAk )
+ ; /* do nothing */
+#ifdef HAVE_NTRU
+ else if (cert->keyOID == NTRUk ) {
+ const byte* key = &cert->source[tmpIdx];
+ byte* next = (byte*)key;
+ word16 keyLen;
+ byte keyBlob[MAX_NTRU_KEY_SZ];
+
+ word32 rc = crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
+ &keyLen, NULL, &next);
+
+ if (rc != NTRU_OK)
+ return ASN_NTRU_KEY_E;
+ if (keyLen > sizeof(keyBlob))
+ return ASN_NTRU_KEY_E;
+
+ rc = crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key, &keyLen,
+ keyBlob, &next);
+ if (rc != NTRU_OK)
+ return ASN_NTRU_KEY_E;
+
+ if ( (next - key) < 0)
+ return ASN_NTRU_KEY_E;
+
+ cert->srcIdx = tmpIdx + (next - key);
+
+ cert->publicKey = (byte*) XMALLOC(keyLen, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (cert->publicKey == NULL)
+ return MEMORY_E;
+ memcpy(cert->publicKey, keyBlob, keyLen);
+ cert->pubKeyStored = 1;
+ cert->pubKeySize = keyLen;
+ }
+#endif
+ else
+ return ASN_UNKNOWN_OID_E;
+
+ return StoreKey(cert);
+}
+
+
+/* process NAME, either issuer or subject */
+static int GetName(DecodedCert* cert, int nameType)
+{
+ Sha sha;
+ int length; /* length of all distinguished names */
+ int dummy;
+ char* full = (nameType == ISSUER) ? cert->issuer : cert->subject;
+ word32 idx = 0;
+
+ InitSha(&sha);
+
+ if (GetSequence(cert->source, &cert->srcIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ length += cert->srcIdx;
+
+ while (cert->srcIdx < (word32)length) {
+ byte b;
+ byte joint[2];
+ int oidSz;
+
+ if (GetSet(cert->source, &cert->srcIdx, &dummy) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(cert->source, &cert->srcIdx, &dummy) < 0)
+ return ASN_PARSE_E;
+
+ b = cert->source[cert->srcIdx++];
+ if (b != ASN_OBJECT_ID)
+ return ASN_OBJECT_ID_E;
+
+ if (GetLength(cert->source, &cert->srcIdx, &oidSz) < 0)
+ return ASN_PARSE_E;
+
+ XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
+
+ /* v1 name types */
+ if (joint[0] == 0x55 && joint[1] == 0x04) {
+ byte id;
+ byte copy = FALSE;
+ int strLen;
+
+ cert->srcIdx += 2;
+ id = cert->source[cert->srcIdx++];
+ b = cert->source[cert->srcIdx++]; /* strType */
+
+ if (GetLength(cert->source, &cert->srcIdx, &strLen) < 0)
+ return ASN_PARSE_E;
+
+ if (strLen > (int)(ASN_NAME_MAX - idx))
+ return ASN_PARSE_E;
+
+ if (4 > (ASN_NAME_MAX - idx)) /* make sure room for biggest */
+ return ASN_PARSE_E; /* pre fix header too "/CN=" */
+
+ if (id == ASN_COMMON_NAME) {
+ if (nameType == SUBJECT) {
+ cert->subjectCN = (char *)&cert->source[cert->srcIdx];
+ cert->subjectCNLen = strLen;
+ }
+
+ XMEMCPY(&full[idx], "/CN=", 4);
+ idx += 4;
+ copy = TRUE;
+ }
+ else if (id == ASN_SUR_NAME) {
+ XMEMCPY(&full[idx], "/SN=", 4);
+ idx += 4;
+ copy = TRUE;
+#ifdef CYASSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectSN = (char*)&cert->source[cert->srcIdx];
+ cert->subjectSNLen = strLen;
+ }
+#endif /* CYASSL_CERT_GEN */
+ }
+ else if (id == ASN_COUNTRY_NAME) {
+ XMEMCPY(&full[idx], "/C=", 3);
+ idx += 3;
+ copy = TRUE;
+#ifdef CYASSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectC = (char*)&cert->source[cert->srcIdx];
+ cert->subjectCLen = strLen;
+ }
+#endif /* CYASSL_CERT_GEN */
+ }
+ else if (id == ASN_LOCALITY_NAME) {
+ XMEMCPY(&full[idx], "/L=", 3);
+ idx += 3;
+ copy = TRUE;
+#ifdef CYASSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectL = (char*)&cert->source[cert->srcIdx];
+ cert->subjectLLen = strLen;
+ }
+#endif /* CYASSL_CERT_GEN */
+ }
+ else if (id == ASN_STATE_NAME) {
+ XMEMCPY(&full[idx], "/ST=", 4);
+ idx += 4;
+ copy = TRUE;
+#ifdef CYASSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectST = (char*)&cert->source[cert->srcIdx];
+ cert->subjectSTLen = strLen;
+ }
+#endif /* CYASSL_CERT_GEN */
+ }
+ else if (id == ASN_ORG_NAME) {
+ XMEMCPY(&full[idx], "/O=", 3);
+ idx += 3;
+ copy = TRUE;
+#ifdef CYASSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectO = (char*)&cert->source[cert->srcIdx];
+ cert->subjectOLen = strLen;
+ }
+#endif /* CYASSL_CERT_GEN */
+ }
+ else if (id == ASN_ORGUNIT_NAME) {
+ XMEMCPY(&full[idx], "/OU=", 4);
+ idx += 4;
+ copy = TRUE;
+#ifdef CYASSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectOU = (char*)&cert->source[cert->srcIdx];
+ cert->subjectOULen = strLen;
+ }
+#endif /* CYASSL_CERT_GEN */
+ }
+
+ if (copy) {
+ XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
+ idx += strLen;
+ }
+
+ ShaUpdate(&sha, &cert->source[cert->srcIdx], strLen);
+ cert->srcIdx += strLen;
+ }
+ else {
+ /* skip */
+ byte email = FALSE;
+ int adv;
+
+ if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */
+ email = TRUE;
+
+ cert->srcIdx += oidSz + 1;
+
+ if (GetLength(cert->source, &cert->srcIdx, &adv) < 0)
+ return ASN_PARSE_E;
+
+ if (adv > (int)(ASN_NAME_MAX - idx))
+ return ASN_PARSE_E;
+
+ if (email) {
+ if (14 > (ASN_NAME_MAX - idx))
+ return ASN_PARSE_E;
+ XMEMCPY(&full[idx], "/emailAddress=", 14);
+ idx += 14;
+
+#ifdef CYASSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectEmail = (char*)&cert->source[cert->srcIdx];
+ cert->subjectEmailLen = adv;
+ }
+#endif /* CYASSL_CERT_GEN */
+
+ XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
+ idx += adv;
+ }
+
+ cert->srcIdx += adv;
+ }
+ }
+ full[idx++] = 0;
+
+ if (nameType == ISSUER)
+ ShaFinal(&sha, cert->issuerHash);
+ else
+ ShaFinal(&sha, cert->subjectHash);
+
+ return 0;
+}
+
+
+#ifndef NO_TIME_H
+
+/* to the second */
+static int DateGreaterThan(const struct tm* a, const struct tm* b)
+{
+ if (a->tm_year > b->tm_year)
+ return 1;
+
+ if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon)
+ return 1;
+
+ if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+ a->tm_mday > b->tm_mday)
+ return 1;
+
+ if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+ a->tm_mday == b->tm_mday && a->tm_hour > b->tm_hour)
+ return 1;
+
+ if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+ a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
+ a->tm_min > b->tm_min)
+ return 1;
+
+ if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
+ a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
+ a->tm_min == b->tm_min && a->tm_sec > b->tm_sec)
+ return 1;
+
+ return 0; /* false */
+}
+
+
+static INLINE int DateLessThan(const struct tm* a, const struct tm* b)
+{
+ return !DateGreaterThan(a,b);
+}
+
+
+/* like atoi but only use first byte */
+/* Make sure before and after dates are valid */
+static int ValidateDate(const byte* date, byte format, int dateType)
+{
+ time_t ltime;
+ struct tm certTime;
+ struct tm* localTime;
+ int i = 0;
+
+ ltime = XTIME(0);
+ XMEMSET(&certTime, 0, sizeof(certTime));
+
+ if (format == ASN_UTC_TIME) {
+ if (btoi(date[0]) >= 5)
+ certTime.tm_year = 1900;
+ else
+ certTime.tm_year = 2000;
+ }
+ else { /* format == GENERALIZED_TIME */
+ certTime.tm_year += btoi(date[i++]) * 1000;
+ certTime.tm_year += btoi(date[i++]) * 100;
+ }
+
+ GetTime(&certTime.tm_year, date, &i); certTime.tm_year -= 1900; /* adjust */
+ GetTime(&certTime.tm_mon, date, &i); certTime.tm_mon -= 1; /* adjust */
+ GetTime(&certTime.tm_mday, date, &i);
+ GetTime(&certTime.tm_hour, date, &i);
+ GetTime(&certTime.tm_min, date, &i);
+ GetTime(&certTime.tm_sec, date, &i);
+
+ if (date[i] != 'Z') /* only Zulu supported for this profile */
+ return 0;
+
+ localTime = XGMTIME(<ime);
+
+ if (dateType == BEFORE) {
+ if (DateLessThan(localTime, &certTime))
+ return 0;
+ }
+ else
+ if (DateGreaterThan(localTime, &certTime))
+ return 0;
+
+ return 1;
+}
+
+#endif /* NO_TIME_H */
+
+
+static int GetDate(DecodedCert* cert, int dateType)
+{
+ int length;
+ byte date[MAX_DATE_SIZE];
+ byte b = cert->source[cert->srcIdx++];
+
+ if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME)
+ return ASN_TIME_E;
+
+ if (GetLength(cert->source, &cert->srcIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
+ return ASN_DATE_SZ_E;
+
+ XMEMCPY(date, &cert->source[cert->srcIdx], length);
+ cert->srcIdx += length;
+
+ if (!XVALIDATE_DATE(date, b, dateType)) {
+ if (dateType == BEFORE)
+ return ASN_BEFORE_DATE_E;
+ else
+ return ASN_AFTER_DATE_E;
+ }
+
+ return 0;
+}
+
+
+static int GetValidity(DecodedCert* cert, int verify)
+{
+ int length;
+ int badDate = 0;
+
+ if (GetSequence(cert->source, &cert->srcIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ if (GetDate(cert, BEFORE) < 0 && verify)
+ badDate = ASN_BEFORE_DATE_E; /* continue parsing */
+
+ if (GetDate(cert, AFTER) < 0 && verify)
+ return ASN_AFTER_DATE_E;
+
+ if (badDate != 0)
+ return badDate;
+
+ return 0;
+}
+
+
+static int DecodeToKey(DecodedCert* cert, word32 inSz, int verify)
+{
+ int badDate = 0;
+ int ret;
+
+ if ( (ret = GetCertHeader(cert, inSz)) < 0)
+ return ret;
+
+ if ( (ret = GetAlgoId(cert->source, &cert->srcIdx,&cert->signatureOID)) < 0)
+ return ret;
+
+ if ( (ret = GetName(cert, ISSUER)) < 0)
+ return ret;
+
+ if ( (ret = GetValidity(cert, verify)) < 0)
+ badDate = ret;
+
+ if ( (ret = GetName(cert, SUBJECT)) < 0)
+ return ret;
+
+ if ( (ret = GetKey(cert)) < 0)
+ return ret;
+
+ if (badDate != 0)
+ return badDate;
+
+ return ret;
+}
+
+
+static int GetSignature(DecodedCert* cert)
+{
+ int length;
+ byte b = cert->source[cert->srcIdx++];
+
+ if (b != ASN_BIT_STRING)
+ return ASN_BITSTR_E;
+
+ if (GetLength(cert->source, &cert->srcIdx, &length) < 0)
+ return ASN_PARSE_E;
+
+ cert->sigLength = length;
+
+ b = cert->source[cert->srcIdx++];
+ if (b != 0x00)
+ return ASN_EXPECT_0_E;
+
+ cert->sigLength--;
+ cert->signature = &cert->source[cert->srcIdx];
+ cert->srcIdx += cert->sigLength;
+
+ return 0;
+}
+
+
+static word32 SetDigest(const byte* digest, word32 digSz, byte* output)
+{
+ output[0] = ASN_OCTET_STRING;
+ output[1] = digSz;
+ XMEMCPY(&output[2], digest, digSz);
+
+ return digSz + 2;
+}
+
+
+static word32 BytePrecision(word32 value)
+{
+ word32 i;
+ for (i = sizeof(value); i; --i)
+ if (value >> (i - 1) * 8)
+ break;
+
+ return i;
+}
+
+
+static word32 SetLength(word32 length, byte* output)
+{
+ word32 i = 0, j;
+
+ if (length < ASN_LONG_LENGTH)
+ output[i++] = length;
+ else {
+ output[i++] = BytePrecision(length) | ASN_LONG_LENGTH;
+
+ for (j = BytePrecision(length); j; --j) {
+ output[i] = length >> (j - 1) * 8;
+ i++;
+ }
+ }
+
+ return i;
+}
+
+
+static word32 SetSequence(word32 len, byte* output)
+{
+ output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
+ return SetLength(len, output + 1) + 1;
+}
+
+
+static word32 SetAlgoID(int algoOID, byte* output, int type)
+{
+ /* adding TAG_NULL and 0 to end */
+
+ /* hashTypes */
+ static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00 };
+ static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00 };
+ static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x02, 0x05, 0x00};
+
+ /* sigTypes */
+ static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x04, 0x05, 0x00};
+
+ /* keyTypes */
+ static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00};
+
+ int algoSz = 0;
+ word32 idSz, seqSz;
+ const byte* algoName = 0;
+ byte ID_Length[MAX_LENGTH_SZ];
+ byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
+
+ if (type == hashType) {
+ switch (algoOID) {
+ case SHAh:
+ algoSz = sizeof(shaAlgoID);
+ algoName = shaAlgoID;
+ break;
+
+ case MD2h:
+ algoSz = sizeof(md2AlgoID);
+ algoName = md2AlgoID;
+ break;
+
+ case MD5h:
+ algoSz = sizeof(md5AlgoID);
+ algoName = md5AlgoID;
+ break;
+
+ default:
+ return 0; /* UNKOWN_HASH_E; */
+ }
+ }
+ else if (type == sigType) { /* sigType */
+ switch (algoOID) {
+ case MD5wRSA:
+ algoSz = sizeof(md5wRSA_AlgoID);
+ algoName = md5wRSA_AlgoID;
+ break;
+
+ default:
+ return 0; /* UNKOWN_HASH_E; */
+ }
+ }
+ else if (type == keyType) { /* keyType */
+ switch (algoOID) {
+ case RSAk:
+ algoSz = sizeof(RSA_AlgoID);
+ algoName = RSA_AlgoID;
+ break;
+
+ default:
+ return 0; /* UNKOWN_HASH_E; */
+ }
+ }
+ else
+ return 0; /* UNKNOWN_TYPE */
+
+
+ idSz = SetLength(algoSz - 2, ID_Length); /* don't include TAG_NULL/0 */
+ seqSz = SetSequence(idSz + algoSz + 1, seqArray);
+ seqArray[seqSz++] = ASN_OBJECT_ID;
+
+ XMEMCPY(output, seqArray, seqSz);
+ XMEMCPY(output + seqSz, ID_Length, idSz);
+ XMEMCPY(output + seqSz + idSz, algoName, algoSz);
+
+ return seqSz + idSz + algoSz;
+
+}
+
+
+word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID)
+{
+ byte digArray[MAX_ENCODED_DIG_SZ];
+ byte algoArray[MAX_ALGO_SZ];
+ byte seqArray[MAX_SEQ_SZ];
+ word32 encDigSz, algoSz, seqSz;
+
+ encDigSz = SetDigest(digest, digSz, digArray);
+ algoSz = SetAlgoID(hashOID, algoArray, hashType);
+ seqSz = SetSequence(encDigSz + algoSz, seqArray);
+
+ XMEMCPY(out, seqArray, seqSz);
+ XMEMCPY(out + seqSz, algoArray, algoSz);
+ XMEMCPY(out + seqSz + algoSz, digArray, encDigSz);
+
+ return encDigSz + algoSz + seqSz;
+}
+
+
+/* return true (1) for Confirmation */
+static int ConfirmSignature(DecodedCert* cert, const byte* key, word32 keySz,
+ word32 keyOID)
+{
+ byte digest[SHA_DIGEST_SIZE]; /* max size */
+ int hashType, digestSz, ret;
+
+ if (cert->signatureOID == MD5wRSA) {
+ Md5 md5;
+ InitMd5(&md5);
+ Md5Update(&md5, cert->source + cert->certBegin,
+ cert->sigIndex - cert->certBegin);
+ Md5Final(&md5, digest);
+ hashType = MD5h;
+ digestSz = MD5_DIGEST_SIZE;
+ }
+ else if (cert->signatureOID == SHAwRSA || cert->signatureOID == SHAwDSA) {
+ Sha sha;
+ InitSha(&sha);
+ ShaUpdate(&sha, cert->source + cert->certBegin,
+ cert->sigIndex - cert->certBegin);
+ ShaFinal(&sha, digest);
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+ }
+ else
+ return 0; /* ASN_SIG_HASH_E; */
+
+ if (keyOID == RSAk) {
+ RsaKey pubKey;
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ byte plain[MAX_ENCODED_SIG_SZ];
+ word32 idx = 0;
+ int sigSz, verifySz;
+ byte* out;
+
+ if (cert->sigLength > MAX_ENCODED_SIG_SZ)
+ return 0; /* the key is too big */
+
+ InitRsaKey(&pubKey, cert->heap);
+ if (RsaPublicKeyDecode(key, &idx, &pubKey, keySz) < 0)
+ ret = 0; /* ASN_KEY_DECODE_E; */
+
+ else {
+ XMEMCPY(plain, cert->signature, cert->sigLength);
+ if ( (verifySz = RsaSSL_VerifyInline(plain, cert->sigLength, &out,
+ &pubKey)) < 0)
+ ret = 0; /* ASN_VERIFY_E; */
+ else {
+ /* make sure we're right justified */
+ sigSz = EncodeSignature(encodedSig, digest, digestSz, hashType);
+ if (sigSz != verifySz || XMEMCMP(out, encodedSig, sigSz) != 0)
+ ret = 0; /* ASN_VERIFY_MATCH_E; */
+ else
+ ret = 1; /* match */
+ }
+ }
+ FreeRsaKey(&pubKey);
+ return ret;
+ }
+ else
+ return 0; /* ASN_SIG_KEY_E; */
+}
+
+
+int ParseCert(DecodedCert* cert, word32 inSz, int type, int verify,
+ Signer* signers)
+{
+ int ret;
+ char* ptr;
+
+ ret = ParseCertRelative(cert, inSz, type, verify, signers);
+ if (ret < 0)
+ return ret;
+
+ if (cert->subjectCNLen > 0) {
+ ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap,
+ DYNAMIC_TYPE_SUBJECT_CN);
+ if (ptr == NULL)
+ return MEMORY_E;
+ XMEMCPY(ptr, cert->subjectCN, cert->subjectCNLen);
+ ptr[cert->subjectCNLen] = '\0';
+ cert->subjectCN = ptr;
+ cert->subjectCNLen = 0;
+ }
+
+ if (cert->keyOID == RSAk && cert->pubKeySize > 0) {
+ ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (ptr == NULL)
+ return MEMORY_E;
+ XMEMCPY(ptr, cert->publicKey, cert->pubKeySize);
+ cert->publicKey = (byte *)ptr;
+ cert->pubKeyStored = 1;
+ }
+
+ return ret;
+}
+
+
+int ParseCertRelative(DecodedCert* cert, word32 inSz, int type, int verify,
+ Signer* signers)
+{
+ word32 confirmOID;
+ int ret;
+ int badDate = 0;
+ int confirm = 0;
+
+ if ((ret = DecodeToKey(cert, inSz, verify)) < 0) {
+ if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
+ badDate = ret;
+ else
+ return ret;
+ }
+
+ if (cert->srcIdx != cert->sigIndex)
+ cert->srcIdx = cert->sigIndex;
+
+ if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID)) < 0)
+ return ret;
+
+ if ((ret = GetSignature(cert)) < 0)
+ return ret;
+
+ if (confirmOID != cert->signatureOID)
+ return ASN_SIG_OID_E;
+
+ if (verify && type != CA_TYPE) {
+ while (signers) {
+ if (XMEMCMP(cert->issuerHash, signers->hash, SHA_DIGEST_SIZE)
+ == 0) {
+ /* other confirm */
+ if (!ConfirmSignature(cert, signers->publicKey,
+ signers->pubKeySize, signers->keyOID))
+ return ASN_SIG_CONFIRM_E;
+ else {
+ confirm = 1;
+ break;
+ }
+ }
+ signers = signers->next;
+ }
+ if (!confirm)
+ return ASN_SIG_CONFIRM_E;
+ }
+ if (badDate != 0)
+ return badDate;
+
+ return 0;
+}
+
+
+Signer* MakeSigner(void* heap)
+{
+ Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap,
+ DYNAMIC_TYPE_SIGNER);
+ if (signer) {
+ signer->name = 0;
+ signer->publicKey = 0;
+ signer->next = 0;
+ }
+
+ return signer;
+}
+
+
+void FreeSigners(Signer* signer, void* heap)
+{
+ Signer* next = signer;
+
+ while( (signer = next) ) {
+ next = signer->next;
+ XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+ XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
+ }
+}
+
+
+void CTaoCryptErrorString(int error, char* buffer)
+{
+ const int max = MAX_ERROR_SZ; /* shorthand */
+
+#ifdef NO_ERROR_STRINGS
+
+ XSTRNCPY(buffer, "no support for error strings built in", max);
+
+#else
+
+ switch (error) {
+
+ case OPEN_RAN_E :
+ XSTRNCPY(buffer, "opening random device error", max);
+ break;
+
+ case READ_RAN_E :
+ XSTRNCPY(buffer, "reading random device error", max);
+ break;
+
+ case WINCRYPT_E :
+ XSTRNCPY(buffer, "windows crypt init error", max);
+ break;
+
+ case CRYPTGEN_E :
+ XSTRNCPY(buffer, "windows crypt generation error", max);
+ break;
+
+ case RAN_BLOCK_E :
+ XSTRNCPY(buffer, "random device read would block error", max);
+ break;
+
+ case MP_INIT_E :
+ XSTRNCPY(buffer, "mp_init error state", max);
+ break;
+
+ case MP_READ_E :
+ XSTRNCPY(buffer, "mp_read error state", max);
+ break;
+
+ case MP_EXPTMOD_E :
+ XSTRNCPY(buffer, "mp_exptmod error state", max);
+ break;
+
+ case MP_TO_E :
+ XSTRNCPY(buffer, "mp_to_xxx error state, can't convert", max);
+ break;
+
+ case MP_SUB_E :
+ XSTRNCPY(buffer, "mp_sub error state, can't subtract", max);
+ break;
+
+ case MP_ADD_E :
+ XSTRNCPY(buffer, "mp_add error state, can't add", max);
+ break;
+
+ case MP_MUL_E :
+ XSTRNCPY(buffer, "mp_mul error state, can't multiply", max);
+ break;
+
+ case MP_MULMOD_E :
+ XSTRNCPY(buffer, "mp_mulmod error state, can't multiply mod", max);
+ break;
+
+ case MP_MOD_E :
+ XSTRNCPY(buffer, "mp_mod error state, can't mod", max);
+ break;
+
+ case MP_INVMOD_E :
+ XSTRNCPY(buffer, "mp_invmod error state, can't inv mod", max);
+ break;
+
+ case MP_CMP_E :
+ XSTRNCPY(buffer, "mp_cmp error state", max);
+ break;
+
+ case MEMORY_E :
+ XSTRNCPY(buffer, "out of memory error", max);
+ break;
+
+ case RSA_WRONG_TYPE_E :
+ XSTRNCPY(buffer, "RSA wrong block type for RSA function", max);
+ break;
+
+ case RSA_BUFFER_E :
+ XSTRNCPY(buffer, "RSA buffer error, output too small or input too big",
+ max);
+ break;
+
+ case BUFFER_E :
+ XSTRNCPY(buffer, "Buffer error, output too small or input too big", max);
+ break;
+
+ case ALGO_ID_E :
+ XSTRNCPY(buffer, "Setting Cert AlogID error", max);
+ break;
+
+ case PUBLIC_KEY_E :
+ XSTRNCPY(buffer, "Setting Cert Public Key error", max);
+ break;
+
+ case DATE_E :
+ XSTRNCPY(buffer, "Setting Cert Date validity error", max);
+ break;
+
+ case SUBJECT_E :
+ XSTRNCPY(buffer, "Setting Cert Subject name error", max);
+ break;
+
+ case ISSUER_E :
+ XSTRNCPY(buffer, "Setting Cert Issuer name error", max);
+ break;
+
+ case ASN_PARSE_E :
+ XSTRNCPY(buffer, "ASN parsing error, invalid input", max);
+ break;
+
+ case ASN_VERSION_E :
+ XSTRNCPY(buffer, "ASN version error, invalid number", max);
+ break;
+
+ case ASN_GETINT_E :
+ XSTRNCPY(buffer, "ASN get big int error, invalid data", max);
+ break;
+
+ case ASN_RSA_KEY_E :
+ XSTRNCPY(buffer, "ASN key init error, invalid input", max);
+ break;
+
+ case ASN_OBJECT_ID_E :
+ XSTRNCPY(buffer, "ASN object id error, invalid id", max);
+ break;
+
+ case ASN_TAG_NULL_E :
+ XSTRNCPY(buffer, "ASN tag error, not null", max);
+ break;
+
+ case ASN_EXPECT_0_E :
+ XSTRNCPY(buffer, "ASN expect error, not zero", max);
+ break;
+
+ case ASN_BITSTR_E :
+ XSTRNCPY(buffer, "ASN bit string error, wrong id", max);
+ break;
+
+ case ASN_UNKNOWN_OID_E :
+ XSTRNCPY(buffer, "ASN oid error, unknown sum id", max);
+ break;
+
+ case ASN_DATE_SZ_E :
+ XSTRNCPY(buffer, "ASN date error, bad size", max);
+ break;
+
+ case ASN_BEFORE_DATE_E :
+ XSTRNCPY(buffer, "ASN date error, current date before", max);
+ break;
+
+ case ASN_AFTER_DATE_E :
+ XSTRNCPY(buffer, "ASN date error, current date after", max);
+ break;
+
+ case ASN_SIG_OID_E :
+ XSTRNCPY(buffer, "ASN signature error, mismatched oid", max);
+ break;
+
+ case ASN_TIME_E :
+ XSTRNCPY(buffer, "ASN time error, unkown time type", max);
+ break;
+
+ case ASN_INPUT_E :
+ XSTRNCPY(buffer, "ASN input error, not enough data", max);
+ break;
+
+ case ASN_SIG_CONFIRM_E :
+ XSTRNCPY(buffer, "ASN sig error, confirm failure", max);
+ break;
+
+ case ASN_SIG_HASH_E :
+ XSTRNCPY(buffer, "ASN sig error, unsupported hash type", max);
+ break;
+
+ case ASN_SIG_KEY_E :
+ XSTRNCPY(buffer, "ASN sig error, unsupported key type", max);
+ break;
+
+ case ASN_DH_KEY_E :
+ XSTRNCPY(buffer, "ASN key init error, invalid input", max);
+ break;
+
+ case ASN_NTRU_KEY_E :
+ XSTRNCPY(buffer, "ASN NTRU key decode error, invalid input", max);
+ break;
+
+ default:
+ XSTRNCPY(buffer, "unknown error number", max);
+
+ }
+
+#endif /* NO_ERROR_STRINGS */
+
+}
+
+
+#if defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN)
+
+static int SetMyVersion(word32 version, byte* output, int header)
+{
+ int i = 0;
+
+ if (header) {
+ output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
+ output[i++] = ASN_BIT_STRING;
+ }
+ output[i++] = ASN_INTEGER;
+ output[i++] = 0x01;
+ output[i++] = version;
+
+ return i;
+}
+
+
+int DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
+ int type)
+{
+ char header[80];
+ char footer[80];
+
+ int headerLen;
+ int footerLen;
+ int i;
+ int outLen; /* return length or error */
+
+ if (type == CERT_TYPE) {
+ XSTRNCPY(header, "-----BEGIN CERTIFICATE-----\n", sizeof(header));
+ XSTRNCPY(footer, "-----END CERTIFICATE-----\n", sizeof(footer));
+ } else {
+ XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----\n", sizeof(header));
+ XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----\n", sizeof(footer));
+ }
+
+ headerLen = XSTRLEN(header);
+ footerLen = XSTRLEN(footer);
+
+ if (!der || !output)
+ return -1;
+
+ /* don't even try if outSz too short */
+ if (outSz < headerLen + footerLen + derSz)
+ return -1;
+
+ /* header */
+ XMEMCPY(output, header, headerLen);
+ i = headerLen;
+
+ /* body */
+ outLen = outSz; /* input to Base64Encode */
+ if (Base64Encode(der, derSz, output + i, (word32*)&outLen) < 0)
+ return -1;
+ i += outLen;
+
+ /* footer */
+ if ( (i + footerLen) > (int)outSz)
+ return -1;
+ XMEMCPY(output + i, footer, footerLen);
+
+ return outLen + headerLen + footerLen;
+}
+
+
+#endif /* CYASSL_KEY_GEN || CYASSL_CERT_GEN */
+
+
+#ifdef CYASSL_KEY_GEN
+
+
+static mp_int* GetRsaInt(RsaKey* key, int index)
+{
+ if (index == 0)
+ return &key->n;
+ if (index == 1)
+ return &key->e;
+ if (index == 2)
+ return &key->d;
+ if (index == 3)
+ return &key->p;
+ if (index == 4)
+ return &key->q;
+ if (index == 5)
+ return &key->dP;
+ if (index == 6)
+ return &key->dQ;
+ if (index == 7)
+ return &key->u;
+
+ return NULL;
+}
+
+
+/* Convert RsaKey key to DER format, write to output (inLen), return bytes
+ written */
+int RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
+{
+ word32 seqSz, verSz, rawLen, intTotalLen = 0;
+ word32 sizes[RSA_INTS];
+ int i, j, outLen;
+
+ byte seq[MAX_SEQ_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte tmps[RSA_INTS][MAX_RSA_INT_SZ];
+
+ if (!key || !output)
+ return -1;
+
+ if (key->type != RSA_PRIVATE)
+ return -1;
+
+ /* write all big ints from key to DER tmps */
+ for (i = 0; i < RSA_INTS; i++) {
+ mp_int* keyInt = GetRsaInt(key, i);
+ rawLen = mp_unsigned_bin_size(keyInt);
+
+ tmps[i][0] = ASN_INTEGER;
+ sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1; /* int tag */
+
+ if ( (sizes[i] + rawLen) < sizeof(tmps[i])) {
+ int err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]);
+ if (err == MP_OKAY) {
+ sizes[i] += rawLen;
+ intTotalLen += sizes[i];
+ }
+ else
+ return err;
+ }
+ else
+ return -1;
+ }
+
+ /* make headers */
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + intTotalLen, seq);
+
+ outLen = seqSz + verSz + intTotalLen;
+ if (outLen > (int)inLen)
+ return -1;
+
+ /* write to output */
+ XMEMCPY(output, seq, seqSz);
+ j = seqSz;
+ XMEMCPY(output + j, ver, verSz);
+ j += verSz;
+
+ for (i = 0; i < RSA_INTS; i++) {
+ XMEMCPY(output + j, tmps[i], sizes[i]);
+ j += sizes[i];
+ }
+
+ return outLen;
+}
+
+#endif /* CYASSL_KEY_GEN */
+
+
+#ifdef CYASSL_CERT_GEN
+
+/* Initialize and Set Certficate defaults:
+ version = 3 (0x2)
+ serial = 0
+ sigType = MD5_WITH_RSA
+ issuer = blank
+ daysValid = 500
+ selfSigned = 1 (true) use subject as issuer
+ subject = blank
+*/
+void InitCert(Cert* cert)
+{
+ cert->version = 2; /* version 3 is hex 2 */
+ cert->sigType = MD5wRSA;
+ cert->daysValid = 500;
+ cert->selfSigned = 1;
+ cert->bodySz = 0;
+ cert->keyType = RSA_KEY;
+ XMEMSET(cert->serial, 0, SERIAL_SIZE);
+
+ cert->issuer.country[0] = '\0';
+ cert->issuer.state[0] = '\0';
+ cert->issuer.locality[0] = '\0';
+ cert->issuer.sur[0] = '\0';
+ cert->issuer.org[0] = '\0';
+ cert->issuer.unit[0] = '\0';
+ cert->issuer.commonName[0] = '\0';
+ cert->issuer.email[0] = '\0';
+
+ cert->subject.country[0] = '\0';
+ cert->subject.state[0] = '\0';
+ cert->subject.locality[0] = '\0';
+ cert->subject.sur[0] = '\0';
+ cert->subject.org[0] = '\0';
+ cert->subject.unit[0] = '\0';
+ cert->subject.commonName[0] = '\0';
+ cert->subject.email[0] = '\0';
+}
+
+
+/* DER encoded x509 Certificate */
+typedef struct DerCert {
+ byte size[MAX_LENGTH_SZ]; /* length encoded */
+ byte version[MAX_VERSION_SZ]; /* version encoded */
+ byte serial[SERIAL_SIZE + MAX_LENGTH_SZ]; /* serial number encoded */
+ byte sigAlgo[MAX_ALGO_SZ]; /* signature algo encoded */
+ byte issuer[ASN_NAME_MAX]; /* issuer encoded */
+ byte subject[ASN_NAME_MAX]; /* subject encoded */
+ byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */
+ byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */
+ int sizeSz; /* encoded size length */
+ int versionSz; /* encoded version length */
+ int serialSz; /* encoded serial length */
+ int sigAlgoSz; /* enocded sig alog length */
+ int issuerSz; /* encoded issuer length */
+ int subjectSz; /* encoded subject length */
+ int validitySz; /* encoded validity length */
+ int publicKeySz; /* encoded public key length */
+ int total; /* total encoded lengths */
+} DerCert;
+
+
+/* Write a set header to output */
+static word32 SetSet(word32 len, byte* output)
+{
+ output[0] = ASN_SET | ASN_CONSTRUCTED;
+ return SetLength(len, output + 1) + 1;
+}
+
+
+/* Write a serial number to output */
+static int SetSerial(const byte* serial, byte* output)
+{
+ int length = 0;
+
+ output[length++] = ASN_INTEGER;
+ length += SetLength(SERIAL_SIZE, &output[length]);
+ XMEMCPY(&output[length], serial, SERIAL_SIZE);
+
+ return length + SERIAL_SIZE;
+}
+
+
+/* Write a public RSA key to output */
+static int SetPublicKey(byte* output, RsaKey* key)
+{
+ byte n[MAX_RSA_INT_SZ];
+ byte e[MAX_RSA_E_SZ];
+ byte algo[MAX_ALGO_SZ];
+ byte seq[MAX_SEQ_SZ];
+ byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
+ int nSz;
+ int eSz;
+ int algoSz;
+ int seqSz;
+ int lenSz;
+ int idx;
+ int rawLen;
+
+ /* n */
+ rawLen = mp_unsigned_bin_size(&key->n);
+ n[0] = ASN_INTEGER;
+ nSz = SetLength(rawLen, n + 1) + 1; /* int tag */
+
+ if ( (nSz + rawLen) < sizeof(n)) {
+ int err = mp_to_unsigned_bin(&key->n, n + nSz);
+ if (err == MP_OKAY)
+ nSz += rawLen;
+ else
+ return MP_TO_E;
+ }
+ else
+ return BUFFER_E;
+
+ /* e */
+ rawLen = mp_unsigned_bin_size(&key->e);
+ e[0] = ASN_INTEGER;
+ eSz = SetLength(rawLen, e + 1) + 1; /* int tag */
+
+ if ( (eSz + rawLen) < sizeof(e)) {
+ int err = mp_to_unsigned_bin(&key->e, e + eSz);
+ if (err == MP_OKAY)
+ eSz += rawLen;
+ else
+ return MP_TO_E;
+ }
+ else
+ return BUFFER_E;
+
+ /* headers */
+ algoSz = SetAlgoID(RSAk, algo, keyType);
+ seqSz = SetSequence(nSz + eSz, seq);
+ lenSz = SetLength(seqSz + nSz + eSz + 1, len);
+ len[lenSz++] = 0; /* trailing 0 */
+
+ /* write */
+ idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output);
+ /* 1 is for ASN_BIT_STRING */
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ output[idx++] = ASN_BIT_STRING;
+ /* length */
+ XMEMCPY(output + idx, len, lenSz);
+ idx += lenSz;
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx += seqSz;
+ /* n */
+ XMEMCPY(output + idx, n, nSz);
+ idx += nSz;
+ /* e */
+ XMEMCPY(output + idx, e, eSz);
+ idx += eSz;
+
+ return idx;
+}
+
+
+static INLINE byte itob(int number)
+{
+ return (byte)number + 0x30;
+}
+
+
+/* write time to output, format */
+static void SetTime(struct tm* date, byte* output)
+{
+ int i = 0;
+
+ output[i++] = itob((date->tm_year % 10000) / 1000);
+ output[i++] = itob((date->tm_year % 1000) / 100);
+ output[i++] = itob((date->tm_year % 100) / 10);
+ output[i++] = itob( date->tm_year % 10);
+
+ output[i++] = itob(date->tm_mon / 10);
+ output[i++] = itob(date->tm_mon % 10);
+
+ output[i++] = itob(date->tm_mday / 10);
+ output[i++] = itob(date->tm_mday % 10);
+
+ output[i++] = itob(date->tm_hour / 10);
+ output[i++] = itob(date->tm_hour % 10);
+
+ output[i++] = itob(date->tm_min / 10);
+ output[i++] = itob(date->tm_min % 10);
+
+ output[i++] = itob(date->tm_sec / 10);
+ output[i++] = itob(date->tm_sec % 10);
+
+ output[i] = 'Z'; /* Zulu profiel */
+}
+
+
+/* Set Date validity from now until now + daysValid */
+static int SetValidity(byte* output, int daysValid)
+{
+ byte before[MAX_DATE_SIZE];
+ byte after[MAX_DATE_SIZE];
+
+ int beforeSz;
+ int afterSz;
+ int seqSz;
+
+ time_t ticks;
+ struct tm* now;
+ struct tm local;
+
+ ticks = XTIME(0);
+ now = XGMTIME(&ticks);
+
+ /* before now */
+ local = *now;
+ before[0] = ASN_GENERALIZED_TIME;
+ beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */
+
+ /* adjust */
+ local.tm_year += 1900;
+ local.tm_mon += 1;
+
+ SetTime(&local, before + beforeSz);
+ beforeSz += ASN_GEN_TIME_SZ;
+
+ /* after now + daysValid */
+ local = *now;
+ after[0] = ASN_GENERALIZED_TIME;
+ afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */
+
+ /* add daysValid */
+ local.tm_mday += daysValid;
+ mktime(&local);
+
+ /* adjust */
+ local.tm_year += 1900;
+ local.tm_mon += 1;
+
+ SetTime(&local, after + afterSz);
+ afterSz += ASN_GEN_TIME_SZ;
+
+ /* headers and output */
+ seqSz = SetSequence(beforeSz + afterSz, output);
+ XMEMCPY(output + seqSz, before, beforeSz);
+ XMEMCPY(output + seqSz + beforeSz, after, afterSz);
+
+ return seqSz + beforeSz + afterSz;
+}
+
+
+/* ASN Encoded Name field */
+typedef struct EncodedName {
+ int nameLen; /* actual string value length */
+ int totalLen; /* total encodeding length */
+ int type; /* type of name */
+ int used; /* are we actually using this one */
+ byte encoded[NAME_SIZE * 2]; /* encoding */
+} EncodedName;
+
+
+/* Get Which Name from index */
+static const char* GetOneName(CertName* name, int index)
+{
+ switch (index) {
+ case 0:
+ return name->country;
+ break;
+ case 1:
+ return name->state;
+ break;
+ case 2:
+ return name->locality;
+ break;
+ case 3:
+ return name->sur;
+ break;
+ case 4:
+ return name->org;
+ break;
+ case 5:
+ return name->unit;
+ break;
+ case 6:
+ return name->commonName;
+ break;
+ case 7:
+ return name->email;
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+
+/* Get ASN Name from index */
+static byte GetNameId(int index)
+{
+ switch (index) {
+ case 0:
+ return ASN_COUNTRY_NAME;
+ break;
+ case 1:
+ return ASN_STATE_NAME;
+ break;
+ case 2:
+ return ASN_LOCALITY_NAME;
+ break;
+ case 3:
+ return ASN_SUR_NAME;
+ break;
+ case 4:
+ return ASN_ORG_NAME;
+ break;
+ case 5:
+ return ASN_ORGUNIT_NAME;
+ break;
+ case 6:
+ return ASN_COMMON_NAME;
+ break;
+ case 7:
+ /* email uses different id type */
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+
+/* encode CertName into output, return total bytes written */
+static int SetName(byte* output, CertName* name)
+{
+ int totalBytes = 0, i, idx;
+ EncodedName names[NAME_ENTRIES];
+
+ for (i = 0; i < NAME_ENTRIES; i++) {
+ const char* nameStr = GetOneName(name, i);
+ if (nameStr) {
+ /* bottom up */
+ byte firstLen[MAX_LENGTH_SZ];
+ byte secondLen[MAX_LENGTH_SZ];
+ byte sequence[MAX_SEQ_SZ];
+ byte set[MAX_SET_SZ];
+
+ int email = i == (NAME_ENTRIES - 1) ? 1 : 0;
+ int strLen = XSTRLEN(nameStr);
+ int thisLen = strLen;
+ int firstSz, secondSz, seqSz, setSz;
+
+ if (strLen == 0) { /* no user data for this item */
+ names[i].used = 0;
+ continue;
+ }
+
+ secondSz = SetLength(strLen, secondLen);
+ thisLen += secondSz;
+ if (email) {
+ thisLen += EMAIL_JOINT_LEN;
+ thisLen ++; /* id type */
+ firstSz = SetLength(EMAIL_JOINT_LEN, firstLen);
+ }
+ else {
+ thisLen++; /* str type */
+ thisLen++; /* id type */
+ thisLen += JOINT_LEN;
+ firstSz = SetLength(JOINT_LEN + 1, firstLen);
+ }
+ thisLen += firstSz;
+ thisLen++; /* object id */
+
+ seqSz = SetSequence(thisLen, sequence);
+ thisLen += seqSz;
+ setSz = SetSet(thisLen, set);
+ thisLen += setSz;
+
+ if (thisLen > sizeof(names[i].encoded))
+ return BUFFER_E;
+
+ /* store it */
+ idx = 0;
+ /* set */
+ XMEMCPY(names[i].encoded, set, setSz);
+ idx += setSz;
+ /* seq */
+ XMEMCPY(names[i].encoded + idx, sequence, seqSz);
+ idx += seqSz;
+ /* asn object id */
+ names[i].encoded[idx++] = ASN_OBJECT_ID;
+ /* first length */
+ XMEMCPY(names[i].encoded + idx, firstLen, firstSz);
+ idx += firstSz;
+ if (email) {
+ const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x09, 0x01, 0x16 };
+ /* email joint id */
+ XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
+ idx += sizeof(EMAIL_OID);
+ }
+ else {
+ /* joint id */
+ names[i].encoded[idx++] = 0x55;
+ names[i].encoded[idx++] = 0x04;
+ /* id type */
+ names[i].encoded[idx++] = GetNameId(i);
+ /* str type */
+ names[i].encoded[idx++] = 0x13;
+ }
+ /* second length */
+ XMEMCPY(names[i].encoded + idx, secondLen, secondSz);
+ idx += secondSz;
+ /* str value */
+ XMEMCPY(names[i].encoded + idx, nameStr, strLen);
+ idx += strLen;
+
+ totalBytes += idx;
+ names[i].totalLen = idx;
+ names[i].used = 1;
+ }
+ else
+ names[i].used = 0;
+ }
+
+ /* header */
+ idx = SetSequence(totalBytes, output);
+ totalBytes += idx;
+ if (totalBytes > ASN_NAME_MAX)
+ return BUFFER_E;
+
+ for (i = 0; i < NAME_ENTRIES; i++) {
+ if (names[i].used) {
+ XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
+ idx += names[i].totalLen;
+ }
+ }
+ return totalBytes;
+}
+
+
+/* encode info from cert into DER enocder format */
+static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, RNG* rng,
+ const byte* ntruKey, word16 ntruSz)
+{
+ /* version */
+ der->versionSz = SetMyVersion(cert->version, der->version, TRUE);
+
+ /* serial number */
+ RNG_GenerateBlock(rng, cert->serial, SERIAL_SIZE);
+ cert->serial[0] = 0x01; /* ensure positive */
+ der->serialSz = SetSerial(cert->serial, der->serial);
+
+ /* signature algo */
+ der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType);
+ if (der->sigAlgoSz == 0)
+ return ALGO_ID_E;
+
+ /* public key */
+ if (cert->keyType == RSA_KEY) {
+ der->publicKeySz = SetPublicKey(der->publicKey, rsaKey);
+ if (der->publicKeySz == 0)
+ return PUBLIC_KEY_E;
+ }
+ else {
+#ifdef HAVE_NTRU
+ word32 rc;
+ word16 encodedSz;
+
+ rc = crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
+ ntruKey, &encodedSz, NULL);
+ if (rc != NTRU_OK)
+ return PUBLIC_KEY_E;
+ if (encodedSz > MAX_PUBLIC_KEY_SZ)
+ return PUBLIC_KEY_E;
+
+ rc = crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
+ ntruKey, &encodedSz, der->publicKey);
+ if (rc != NTRU_OK)
+ return PUBLIC_KEY_E;
+
+ der->publicKeySz = encodedSz;
+#endif
+ }
+
+ /* date validity */
+ der->validitySz = SetValidity(der->validity, cert->daysValid);
+ if (der->validitySz == 0)
+ return DATE_E;
+
+ /* subject name */
+ der->subjectSz = SetName(der->subject, &cert->subject);
+ if (der->subjectSz == 0)
+ return SUBJECT_E;
+
+ /* issuer name */
+ der->issuerSz = SetName(der->issuer, cert->selfSigned ?
+ &cert->subject : &cert->issuer);
+ if (der->issuerSz == 0)
+ return ISSUER_E;
+
+ der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
+ der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz;
+
+ return 0;
+}
+
+
+/* write DER encoded cert to buffer, size already checked */
+static int WriteCertBody(DerCert* der, byte* buffer)
+{
+ int idx;
+
+ /* signed part header */
+ idx = SetSequence(der->total, buffer);
+ /* version */
+ XMEMCPY(buffer + idx, der->version, der->versionSz);
+ idx += der->versionSz;
+ /* serial */
+ XMEMCPY(buffer + idx, der->serial, der->serialSz);
+ idx += der->serialSz;
+ /* sig algo */
+ XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz);
+ idx += der->sigAlgoSz;
+ /* issuer */
+ XMEMCPY(buffer + idx, der->issuer, der->issuerSz);
+ idx += der->issuerSz;
+ /* validity */
+ XMEMCPY(buffer + idx, der->validity, der->validitySz);
+ idx += der->validitySz;
+ /* subject */
+ XMEMCPY(buffer + idx, der->subject, der->subjectSz);
+ idx += der->subjectSz;
+ /* public key */
+ XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
+ idx += der->publicKeySz;
+
+ return idx;
+}
+
+
+/* Make MD5wRSA signature from buffer (sz), write to sig (sigSz) */
+static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz,
+ RsaKey* key, RNG* rng)
+{
+ byte digest[SHA_DIGEST_SIZE]; /* max size */
+ byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ];
+ int encSigSz, digestSz, hashType;
+ Md5 md5; /* md5 for now */
+
+ InitMd5(&md5);
+ Md5Update(&md5, buffer, sz);
+ Md5Final(&md5, digest);
+ digestSz = MD5_DIGEST_SIZE;
+ hashType = MD5h;
+
+ /* signature */
+ encSigSz = EncodeSignature(encSig, digest, digestSz, hashType);
+ return RsaSSL_Sign(encSig, encSigSz, sig, sigSz, key, rng);
+}
+
+
+/* add signature to end of buffer, size of buffer assumed checked, return
+ new length */
+static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz)
+{
+ byte seq[MAX_SEQ_SZ];
+ int idx = bodySz, seqSz;
+
+ /* algo */
+ idx += SetAlgoID(MD5wRSA, buffer + idx, sigType);
+ /* bit string */
+ buffer[idx++] = ASN_BIT_STRING;
+ /* length */
+ idx += SetLength(sigSz + 1, buffer + idx);
+ buffer[idx++] = 0; /* trailing 0 */
+ /* signature */
+ XMEMCPY(buffer + idx, sig, sigSz);
+ idx += sigSz;
+
+ /* make room for overall header */
+ seqSz = SetSequence(idx, seq);
+ XMEMMOVE(buffer + seqSz, buffer, idx);
+ XMEMCPY(buffer, seq, seqSz);
+
+ return idx + seqSz;
+}
+
+
+/* Make an x509 Certificate v3 any key type from cert input, write to buffer */
+static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
+ RsaKey* rsaKey, RNG* rng, const byte* ntruKey, word16 ntruSz)
+{
+ DerCert der;
+ int ret;
+
+ cert->keyType = rsaKey ? RSA_KEY : NTRU_KEY;
+ ret = EncodeCert(cert, &der, rsaKey, rng, ntruKey, ntruSz);
+ if (ret != 0)
+ return ret;
+
+ if (der.total + MAX_SEQ_SZ * 2 > (int)derSz)
+ return BUFFER_E;
+
+ return cert->bodySz = WriteCertBody(&der, derBuffer);
+}
+
+
+/* Make an x509 Certificate v3 RSA from cert input, write to buffer */
+int MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,RNG* rng)
+{
+ return MakeAnyCert(cert, derBuffer, derSz, rsaKey, rng, NULL, 0);
+}
+
+
+#ifdef HAVE_NTRU
+
+int MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
+ const byte* ntruKey, word16 keySz, RNG* rng)
+{
+ return MakeAnyCert(cert, derBuffer, derSz, NULL, rng, ntruKey, keySz);
+}
+
+#endif /* HAVE_NTRU */
+
+
+int SignCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
+{
+ byte sig[MAX_ENCODED_SIG_SZ];
+ int sigSz;
+ int bodySz = cert->bodySz;
+
+ if (bodySz < 0)
+ return bodySz;
+
+ sigSz = MakeSignature(buffer, bodySz, sig, sizeof(sig), key, rng);
+ if (sigSz < 0)
+ return sigSz;
+
+ if (bodySz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz)
+ return BUFFER_E;
+
+ return AddSignature(buffer, bodySz, sig, sigSz);
+}
+
+
+int MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
+{
+ int ret = MakeCert(cert, buffer, buffSz, key, rng);
+
+ if (ret < 0)
+ return ret;
+
+ return SignCert(cert, buffer, buffSz, key, rng);
+}
+
+
+/* forward from CyaSSL */
+int CyaSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz);
+
+#ifndef NO_FILESYSTEM
+
+int SetIssuer(Cert* cert, const char* issuerCertFile)
+{
+ DecodedCert decoded;
+ byte der[8192];
+ int derSz = CyaSSL_PemCertToDer(issuerCertFile, der, sizeof(der));
+ int ret;
+ int sz;
+
+ if (derSz < 0)
+ return derSz;
+
+ cert->selfSigned = 0;
+
+ InitDecodedCert(&decoded, der, 0);
+ ret = ParseCertRelative(&decoded, derSz, CA_TYPE, NO_VERIFY, 0);
+
+ if (ret < 0)
+ return ret;
+
+ if (decoded.subjectCN) {
+ sz = (decoded.subjectCNLen < NAME_SIZE) ? decoded.subjectCNLen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.commonName, decoded.subjectCN, NAME_SIZE);
+ cert->issuer.commonName[sz] = 0;
+ }
+ if (decoded.subjectC) {
+ sz = (decoded.subjectCLen < NAME_SIZE) ? decoded.subjectCLen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.country, decoded.subjectC, NAME_SIZE);
+ cert->issuer.country[sz] = 0;
+ }
+ if (decoded.subjectST) {
+ sz = (decoded.subjectSTLen < NAME_SIZE) ? decoded.subjectSTLen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.state, decoded.subjectST, NAME_SIZE);
+ cert->issuer.state[sz] = 0;
+ }
+ if (decoded.subjectL) {
+ sz = (decoded.subjectLLen < NAME_SIZE) ? decoded.subjectLLen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.locality, decoded.subjectL, NAME_SIZE);
+ cert->issuer.locality[sz] = 0;
+ }
+ if (decoded.subjectO) {
+ sz = (decoded.subjectOLen < NAME_SIZE) ? decoded.subjectOLen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.org, decoded.subjectO, NAME_SIZE);
+ cert->issuer.org[sz] = 0;
+ }
+ if (decoded.subjectOU) {
+ sz = (decoded.subjectOULen < NAME_SIZE) ? decoded.subjectOULen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.unit, decoded.subjectOU, NAME_SIZE);
+ cert->issuer.unit[sz] = 0;
+ }
+ if (decoded.subjectSN) {
+ sz = (decoded.subjectSNLen < NAME_SIZE) ? decoded.subjectSNLen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.sur, decoded.subjectSN, NAME_SIZE);
+ cert->issuer.sur[sz] = 0;
+ }
+ if (decoded.subjectEmail) {
+ sz = (decoded.subjectEmailLen < NAME_SIZE) ? decoded.subjectEmailLen :
+ NAME_SIZE - 1;
+ strncpy(cert->issuer.email, decoded.subjectEmail, NAME_SIZE);
+ cert->issuer.email[sz] = 0;
+ }
+
+ FreeDecodedCert(&decoded);
+
+ return 0;
+}
+
+#endif /* NO_FILESYSTEM */
+#endif /* CYASSL_CERT_GEN */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/asn.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,290 @@
+/* asn.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_ASN_H
+#define CTAO_CRYPT_ASN_H
+
+#include "types.h"
+#include "ctc_rsa.h"
+#include "ctc_dh.h"
+#include "ctc_dsa.h"
+#include "ctc_sha.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* ASN Tags */
+enum ASN_Tags {
+ ASN_INTEGER = 0x02,
+ ASN_BIT_STRING = 0x03,
+ ASN_OCTET_STRING = 0x04,
+ ASN_TAG_NULL = 0x05,
+ ASN_OBJECT_ID = 0x06,
+ ASN_SEQUENCE = 0x10,
+ ASN_SET = 0x11,
+ ASN_UTC_TIME = 0x17,
+ ASN_GENERALIZED_TIME = 0x18,
+ ASN_LONG_LENGTH = 0x80
+};
+
+
+enum ASN_Flags{
+ ASN_CONSTRUCTED = 0x20,
+ ASN_CONTEXT_SPECIFIC = 0x80
+};
+
+enum DN_Tags {
+ ASN_COMMON_NAME = 0x03, /* CN */
+ ASN_SUR_NAME = 0x04, /* SN */
+ ASN_COUNTRY_NAME = 0x06, /* C */
+ ASN_LOCALITY_NAME = 0x07, /* L */
+ ASN_STATE_NAME = 0x08, /* ST */
+ ASN_ORG_NAME = 0x0a, /* O */
+ ASN_ORGUNIT_NAME = 0x0b /* OU */
+};
+
+enum Misc_ASN {
+ ASN_NAME_MAX = 256,
+ SHA_SIZE = 20,
+ RSA_INTS = 8, /* RSA ints in private key */
+ MIN_DATE_SIZE = 13,
+ MAX_DATE_SIZE = 32,
+ ASN_GEN_TIME_SZ = 15, /* 7 numbers * 2 + Zulu tag */
+ MAX_ENCODED_SIG_SZ = 512,
+ MAX_SIG_SZ = 256,
+ MAX_ALGO_SZ = 20,
+ MAX_SEQ_SZ = 5, /* enum(seq | con) + length(4) */
+ MAX_SET_SZ = 5, /* enum(set | con) + length(4) */
+ MAX_VERSION_SZ = 5, /* enum + id + version(byte) + (header(2))*/
+ MAX_ENCODED_DIG_SZ = 25, /* sha + enum(bit or octet) + legnth(4) */
+ MAX_RSA_INT_SZ = 517, /* RSA raw sz 4096 for bits + tag + len(4) */
+ MAX_NTRU_KEY_SZ = 610, /* NTRU 112 bit public key */
+ MAX_NTRU_ENC_SZ = 628, /* NTRU 112 bit DER public encoding */
+ MAX_RSA_E_SZ = 16, /* Max RSA public e size */
+ MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
+ /* use bigger NTRU size */
+ MAX_LENGTH_SZ = 4
+};
+
+
+enum Oid_Types {
+ hashType = 0,
+ sigType = 1,
+ keyType = 2
+};
+
+
+enum Sig_Sum {
+ SHAwDSA = 517,
+ MD2wRSA = 646,
+ MD5wRSA = 648,
+ SHAwRSA = 649
+};
+
+enum Hash_Sum {
+ MD2h = 646,
+ MD5h = 649,
+ SHAh = 88
+};
+
+enum Key_Sum {
+ DSAk = 515,
+ RSAk = 645,
+ NTRUk = 364
+};
+
+
+/* Certificate file Type */
+enum CertType {
+ CERT_TYPE = 0,
+ PRIVATEKEY_TYPE,
+ CA_TYPE
+};
+
+
+enum VerifyType {
+ NO_VERIFY = 0,
+ VERIFY = 1
+};
+
+
+typedef struct DecodedCert {
+ byte* publicKey;
+ word32 pubKeySize;
+ int pubKeyStored;
+ word32 certBegin; /* offset to start of cert */
+ word32 sigIndex; /* offset to start of signature */
+ word32 sigLength; /* length of signature */
+ word32 signatureOID; /* sum of algorithm object id */
+ word32 keyOID; /* sum of key algo object id */
+ byte subjectHash[SHA_SIZE]; /* hash of all Names */
+ byte issuerHash[SHA_SIZE]; /* hash of all Names */
+ byte* signature; /* not owned, points into raw cert */
+ char* subjectCN; /* CommonName */
+ int subjectCNLen;
+ char issuer[ASN_NAME_MAX]; /* full name including common name */
+ char subject[ASN_NAME_MAX]; /* full name including common name */
+ int verify; /* Default to yes, but could be off */
+ byte* source; /* byte buffer holder cert, NOT owner */
+ word32 srcIdx; /* current offset into buffer */
+ void* heap; /* for user memory overrides */
+#ifdef CYASSL_CERT_GEN
+ /* easy access to sujbect info for other sign */
+ char* subjectSN;
+ int subjectSNLen;
+ char* subjectC;
+ int subjectCLen;
+ char* subjectL;
+ int subjectLLen;
+ char* subjectST;
+ int subjectSTLen;
+ char* subjectO;
+ int subjectOLen;
+ char* subjectOU;
+ int subjectOULen;
+ char* subjectEmail;
+ int subjectEmailLen;
+#endif /* CYASSL_CERT_GEN */
+} DecodedCert;
+
+
+typedef struct Signer Signer;
+
+/* CA Signers */
+struct Signer {
+ byte* publicKey;
+ word32 pubKeySize;
+ word32 keyOID; /* key type */
+ char* name; /* common name */
+ byte hash[SHA_DIGEST_SIZE]; /* sha hash of names in certificate */
+ Signer* next;
+};
+
+
+void InitDecodedCert(DecodedCert*, byte*, void*);
+void FreeDecodedCert(DecodedCert*);
+int ParseCert(DecodedCert*, word32, int type, int verify, Signer* signer);
+int ParseCertRelative(DecodedCert*, word32, int type, int verify,
+ Signer* signer);
+
+word32 EncodeSignature(byte* out, const byte* digest, word32 digSz,int hashOID);
+
+Signer* MakeSigner(void*);
+void FreeSigners(Signer*, void*);
+
+
+int RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, word32);
+int RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, word32);
+int ToTraditional(byte* buffer, word32 length);
+
+#ifndef NO_DH
+int DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32);
+int DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz);
+#endif
+
+#ifndef NO_DSA
+int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey*, word32);
+int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey*, word32);
+#endif
+
+#ifdef CYASSL_KEY_GEN
+int RsaKeyToDer(RsaKey*, byte* output, word32 inLen);
+#endif
+
+
+#if defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN)
+int DerToPem(const byte* der, word32 derSz, byte* output, word32 outputSz,
+ int type);
+#endif
+
+#ifdef CYASSL_CERT_GEN
+
+enum cert_enums {
+ SERIAL_SIZE = 8,
+ NAME_SIZE = 64,
+ NAME_ENTRIES = 8,
+ JOINT_LEN = 2,
+ EMAIL_JOINT_LEN = 9,
+ RSA_KEY = 10,
+ NTRU_KEY = 11
+};
+
+
+typedef struct CertName {
+ char country[NAME_SIZE];
+ char state[NAME_SIZE];
+ char locality[NAME_SIZE];
+ char sur[NAME_SIZE];
+ char org[NAME_SIZE];
+ char unit[NAME_SIZE];
+ char commonName[NAME_SIZE];
+ char email[NAME_SIZE]; /* !!!! email has to be last !!!! */
+} CertName;
+
+
+/* for user to fill for certificate generation */
+typedef struct Cert {
+ int version; /* x509 version */
+ byte serial[SERIAL_SIZE]; /* serial number */
+ int sigType; /* signature algo type */
+ CertName issuer; /* issuer info */
+ int daysValid; /* validity days */
+ int selfSigned; /* self signed flag */
+ CertName subject; /* subject info */
+ /* internal use only */
+ int bodySz; /* pre sign total size */
+ int keyType; /* public key type of subject */
+} Cert;
+
+
+/* Initialize and Set Certficate defaults:
+ version = 3 (0x2)
+ serial = 0 (Will be randomly generated)
+ sigType = MD5_WITH_RSA
+ issuer = blank
+ daysValid = 500
+ selfSigned = 1 (true) use subject as issuer
+ subject = blank
+ keyType = RSA_KEY (default)
+*/
+void InitCert(Cert*);
+int MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, RNG*);
+int SignCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, RNG*);
+int MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, RNG*);
+int SetIssuer(Cert*, const char*);
+#ifdef HAVE_NTRU
+int MakeNtruCert(Cert*, byte* derBuffer, word32 derSz, const byte* ntruKey,
+ word16 keySz, RNG*);
+#endif
+
+
+#endif /* CYASSL_CERT_GEN */
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_ASN_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/coding.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,229 @@
+/* coding.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "coding.h"
+
+
+enum {
+ BAD = 0xFF, /* invalid encoding */
+ PAD = '=',
+ PEM_LINE_SZ = 64
+};
+
+
+static
+const byte base64Decode[] = { 62, BAD, BAD, BAD, 63, /* + starts at 0x2B */
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ 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,
+ BAD, BAD, BAD, BAD, BAD, BAD,
+ 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
+ };
+
+
+int Base64Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+ word32 i = 0;
+ word32 j = 0;
+ word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
+
+ plainSz = (plainSz * 3 + 3) / 4;
+ if (plainSz > *outLen) return -1;
+
+ while (inLen > 3) {
+ byte b1, b2, b3;
+ byte e1 = in[j++];
+ byte e2 = in[j++];
+ byte e3 = in[j++];
+ byte e4 = in[j++];
+
+ int pad3 = 0;
+ int pad4 = 0;
+
+ if (e1 == 0) /* end file 0's */
+ break;
+ if (e3 == PAD)
+ pad3 = 1;
+ if (e4 == PAD)
+ pad4 = 1;
+
+ e1 = base64Decode[e1 - 0x2B];
+ e2 = base64Decode[e2 - 0x2B];
+ e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
+ e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
+
+ b1 = (e1 << 2) | (e2 >> 4);
+ b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
+ b3 = ((e3 & 0x3) << 6) | e4;
+
+ out[i++] = b1;
+ if (!pad3)
+ out[i++] = b2;
+ if (!pad4)
+ out[i++] = b3;
+ else
+ break;
+
+ inLen -= 4;
+ if (in[j] == ' ' || in[j] == '\r' || in[j] == '\n') {
+ byte endLine = in[j++];
+ inLen--;
+ while (endLine == ' ') { /* allow trailing whitespace */
+ endLine = in[j++];
+ inLen--;
+ }
+ if (endLine == '\r') {
+ endLine = in[j++];
+ inLen--;
+ }
+ if (endLine != '\n')
+ return -1;
+ }
+ }
+ *outLen = i;
+
+ return 0;
+}
+
+
+#if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN)
+
+static
+const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '+', '/'
+ };
+
+
+/* porting assistance from yaSSL by Raphael HUCK */
+int Base64Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+ word32 i = 0,
+ j = 0,
+ n = 0; /* new line counter */
+
+ word32 outSz = (inLen + 3 - 1) / 3 * 4;
+ outSz += (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ; /* new lines */
+
+ if (outSz > *outLen) return -1;
+
+ while (inLen > 2) {
+ byte b1 = in[j++];
+ byte b2 = in[j++];
+ byte b3 = in[j++];
+
+ /* encoded idx */
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
+ byte e4 = b3 & 0x3F;
+
+ /* store */
+ out[i++] = base64Encode[e1];
+ out[i++] = base64Encode[e2];
+ out[i++] = base64Encode[e3];
+ out[i++] = base64Encode[e4];
+
+ inLen -= 3;
+
+ if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)
+ out[i++] = '\n';
+ }
+
+ /* last integral */
+ if (inLen) {
+ int twoBytes = (inLen == 2);
+
+ byte b1 = in[j++];
+ byte b2 = (twoBytes) ? in[j++] : 0;
+
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = (b2 & 0xF) << 2;
+
+ out[i++] = base64Encode[e1];
+ out[i++] = base64Encode[e2];
+ out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
+ out[i++] = PAD;
+ }
+
+ out[i++] = '\n';
+ if (i != outSz)
+ return -1;
+ *outLen = outSz;
+
+ return 0;
+}
+
+
+static
+const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ 10, 11, 12, 13, 14, 15
+ }; /* A starts at 0x41 not 0x3A */
+
+int Base16Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
+{
+ word32 inIdx = 0;
+ word32 outIdx = 0;
+
+ if (inLen % 2)
+ return -1;
+
+ if (*outLen < (inLen / 2))
+ return -1;
+
+ while (inLen) {
+ byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
+ byte b2 = in[inIdx++] - 0x30;
+
+ /* sanity checks */
+ if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
+ return -1;
+ if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
+ return -1;
+
+ b = hexDecode[b];
+ b2 = hexDecode[b2];
+
+ if (b == BAD || b2 == BAD)
+ return -1;
+
+ out[outIdx++] = (b << 4) | b2;
+ inLen -= 2;
+ }
+
+ *outLen = outIdx;
+ return 0;
+}
+
+
+#endif /* OPENSSL_EXTRA */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/coding.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,47 @@
+/* coding.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_CODING_H
+#define CTAO_CRYPT_CODING_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/* decode needed by CyaSSL */
+int Base64Decode(const byte* in, word32 inLen, byte* out, word32* outLen);
+
+#if defined(OPENSSL_EXTRA) || defined(SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN)
+ /* encode isn't */
+ int Base64Encode(const byte* in, word32 inLen, byte* out, word32* outLen);
+ int Base16Decode(const byte* in, word32 inLen, byte* out, word32* outLen);
+#endif
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_CODING_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_aes.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,84 @@
+/* ctc_aes.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef NO_AES
+
+#ifndef CTAO_CRYPT_AES_H
+#define CTAO_CRYPT_AES_H
+
+
+#include "types.h"
+
+#ifdef CYASSL_AESNI
+
+#include <wmmintrin.h>
+
+#if !defined (ALIGN16)
+ #if defined (__GNUC__)
+ #define ALIGN16 __attribute__ ( (aligned (16)))
+ #elif defined(_MSC_VER)
+ #define ALIGN16 __declspec (align (16))
+ #else
+ #define ALIGN16
+ #endif
+#endif
+
+#endif /* CYASSL_AESNI */
+
+#if !defined (ALIGN16)
+ #define ALIGN16
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+enum {
+ AES_ENCRYPTION = 0,
+ AES_DECRYPTION = 1,
+ AES_BLOCK_SIZE = 16
+};
+
+
+typedef struct Aes {
+ /* AESNI needs key first, rounds 2nd, not sure why yet */
+ ALIGN16 word32 key[60];
+ word32 rounds;
+
+ ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
+ ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */
+} Aes;
+
+
+int AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, int dir);
+void AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz);
+void AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* CTAO_CRYPT_AES_H */
+#endif /* NO_AES */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_dh.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,59 @@
+/* ctc_dh.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef NO_DH
+
+#ifndef CTAO_CRYPT_DH_H
+#define CTAO_CRYPT_DH_H
+
+#include "types.h"
+#include "integer.h"
+#include "random.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/* Diffie-Hellman Key */
+typedef struct DhKey {
+ mp_int p, g; /* group parameters */
+} DhKey;
+
+
+void InitDhKey(DhKey* key);
+void FreeDhKey(DhKey* key);
+
+int DhGenerateKeyPair(DhKey* key, RNG* rng, byte* priv, word32* privSz,
+ byte* pub, word32* pubSz);
+int DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
+ word32 privSz, const byte* otherPub, word32 pubSz);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_DH_H */
+
+#endif /* NO_DH */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_dsa.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,61 @@
+/* ctc_dsa.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef NO_DSA
+
+#ifndef CTAO_CRYPT_DSA_H
+#define CTAO_CRYPT_DSA_H
+
+#include "types.h"
+#include "integer.h"
+#include "random.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+enum {
+ DSA_PUBLIC = 0,
+ DSA_PRIVATE = 1
+};
+
+/* DSA */
+typedef struct DsaKey {
+ mp_int p, q, g, y, x;
+ int type; /* public or private */
+} DsaKey;
+
+
+void InitDsaKey(DsaKey* key);
+void FreeDsaKey(DsaKey* key);
+
+int DsaSign(const byte* digest, byte* out, DsaKey* key, RNG* rng);
+int DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_DSA_H */
+#endif /* NO_DSA */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_hmac.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,85 @@
+/* ctc_hmac.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef NO_HMAC
+
+#ifndef CTAO_CRYPT_HMAC_H
+#define CTAO_CRYPT_HMAC_H
+
+#include "ctc_md5.h"
+#include "ctc_sha.h"
+
+#ifndef NO_SHA256
+ #include "sha256.h"
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+enum {
+ IPAD = 0x36,
+ OPAD = 0x5C,
+#ifndef NO_SHA256
+ INNER_HASH_SIZE = SHA256_DIGEST_SIZE,
+#else
+ INNER_HASH_SIZE = SHA_DIGEST_SIZE,
+ SHA256 = 2, /* hash type unique */
+#endif
+ HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE
+};
+
+
+/* hash union */
+typedef union {
+ Md5 md5;
+ Sha sha;
+ #ifndef NO_SHA256
+ Sha256 sha256;
+ #endif
+} Hash;
+
+/* Hmac digest */
+typedef struct Hmac {
+ Hash hash;
+ word32 ipad[HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/
+ word32 opad[HMAC_BLOCK_SIZE / sizeof(word32)];
+ word32 innerHash[INNER_HASH_SIZE / sizeof(word32)]; /* max size */
+ byte macType; /* md5 sha or sha256 */
+ byte innerHashKeyed; /* keyed flag */
+} Hmac;
+
+
+void HmacSetKey(Hmac*, int type, const byte* key, word32 keySz); /* does init */
+void HmacUpdate(Hmac*, const byte*, word32);
+void HmacFinal(Hmac*, byte*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_HMAC_H */
+
+#endif /* NO_HMAC */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_md4.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,65 @@
+/* ctc_md4.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_MD4
+
+#ifndef CTAO_CRYPT_MD4_H
+#define CTAO_CRYPT_MD4_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/* in bytes */
+enum {
+ MD4_BLOCK_SIZE = 64,
+ MD4_DIGEST_SIZE = 16,
+ MD4_PAD_SIZE = 56
+};
+
+
+/* MD4 digest */
+typedef struct Md4 {
+ word32 buffLen; /* in bytes */
+ word32 loLen; /* length in bytes */
+ word32 hiLen; /* length in bytes */
+ word32 digest[MD4_DIGEST_SIZE / sizeof(word32)];
+ word32 buffer[MD4_BLOCK_SIZE / sizeof(word32)];
+} Md4;
+
+
+void InitMd4(Md4*);
+void Md4Update(Md4*, const byte*, word32);
+void Md4Final(Md4*, byte*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_MD4_H */
+
+#endif /* NO_MD4 */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_md5.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,62 @@
+/* ctc_md5.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_MD5_H
+#define CTAO_CRYPT_MD5_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/* in bytes */
+enum {
+ MD5 = 0, /* hash type unique */
+ MD5_BLOCK_SIZE = 64,
+ MD5_DIGEST_SIZE = 16,
+ MD5_PAD_SIZE = 56
+};
+
+
+/* MD5 digest */
+typedef struct Md5 {
+ word32 buffLen; /* in bytes */
+ word32 loLen; /* length in bytes */
+ word32 hiLen; /* length in bytes */
+ word32 digest[MD5_DIGEST_SIZE / sizeof(word32)];
+ word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)];
+} Md5;
+
+
+void InitMd5(Md5*);
+void Md5Update(Md5*, const byte*, word32);
+void Md5Final(Md5*, byte*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_MD5_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_ripemd.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,65 @@
+/* ctc_ripemd.h
+ *
+ * Copyright (C) 2006-2010 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifdef CYASSL_RIPEMD
+
+#ifndef CTAO_CRYPT_RIPEMD_H
+#define CTAO_CRYPT_RIPEME_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/* in bytes */
+enum {
+ RIPEMD = 3, /* hash type unique */
+ RIPEMD_BLOCK_SIZE = 64,
+ RIPEMD_DIGEST_SIZE = 20,
+ RIPEMD_PAD_SIZE = 56
+};
+
+
+/* RipeMd 160 digest */
+typedef struct RipeMd {
+ word32 buffLen; /* in bytes */
+ word32 loLen; /* length in bytes */
+ word32 hiLen; /* length in bytes */
+ word32 digest[RIPEMD_DIGEST_SIZE / sizeof(word32)];
+ word32 buffer[RIPEMD_BLOCK_SIZE / sizeof(word32)];
+} RipeMd;
+
+
+void InitRipeMd(RipeMd*);
+void RipeMdUpdate(RipeMd*, const byte*, word32);
+void RipeMdFinal(RipeMd*, byte*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_RIPEMD_H */
+#endif /* CYASSL_RIPEMD */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_rsa.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,74 @@
+/* ctc_rsa.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_RSA_H
+#define CTAO_CRYPT_RSA_H
+
+#include "types.h"
+#include "integer.h"
+#include "random.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+enum {
+ RSA_PUBLIC = 0,
+ RSA_PRIVATE = 1
+};
+
+/* RSA */
+typedef struct RsaKey {
+ mp_int n, e, d, p, q, dP, dQ, u;
+ int type; /* public or private */
+ void* heap; /* for user memory overrides */
+} RsaKey;
+
+
+void InitRsaKey(RsaKey* key, void*);
+void FreeRsaKey(RsaKey* key);
+
+int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key, RNG* rng);
+int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key);
+int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key);
+int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key, RNG* rng);
+int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key);
+int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key);
+
+int RsaEncryptSize(RsaKey* key);
+
+#ifdef CYASSL_KEY_GEN
+ int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng);
+#endif
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_RSA_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ctc_sha.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,63 @@
+/* ctc_sha.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_SHA_H
+#define CTAO_CRYPT_SHA_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/* in bytes */
+enum {
+ SHA = 1, /* hash type unique */
+ SHA_BLOCK_SIZE = 64,
+ SHA_DIGEST_SIZE = 20,
+ SHA_PAD_SIZE = 56
+};
+
+
+/* Sha digest */
+typedef struct Sha {
+ word32 buffLen; /* in bytes */
+ word32 loLen; /* length in bytes */
+ word32 hiLen; /* length in bytes */
+ word32 digest[SHA_DIGEST_SIZE / sizeof(word32)];
+ word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)];
+} Sha;
+
+
+void InitSha(Sha*);
+void ShaUpdate(Sha*, const byte*, word32);
+void ShaFinal(Sha*, byte*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_SHA_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cyassl_error.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,111 @@
+/* cyassl_error.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+#ifndef CYASSL_ERROR_H
+#define CYASSL_ERROR_H
+
+#include "error.h" /* CTaoCrypt errors */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+enum CyaSSL_ErrorCodes {
+ PREFIX_ERROR = -202, /* bad index to key rounds */
+ MEMORY_ERROR = -203, /* out of memory */
+ VERIFY_FINISHED_ERROR = -204, /* verify problem on finished */
+ VERIFY_MAC_ERROR = -205, /* verify mac problem */
+ PARSE_ERROR = -206, /* parse error on header */
+ UNKNOWN_HANDSHAKE_TYPE = -207, /* weird handshake type */
+ SOCKET_ERROR_E = -208, /* error state on socket */
+ SOCKET_NODATA = -209, /* expected data, not there */
+ INCOMPLETE_DATA = -210, /* don't have enough data to
+ complete task */
+ UNKNOWN_RECORD_TYPE = -211, /* unknown type in record hdr */
+ DECRYPT_ERROR = -212, /* error during decryption */
+ FATAL_ERROR = -213, /* revcd alert fatal error */
+ ENCRYPT_ERROR = -214, /* error during encryption */
+ FREAD_ERROR = -215, /* fread problem */
+ NO_PEER_KEY = -216, /* need peer's key */
+ NO_PRIVATE_KEY = -217, /* need the private key */
+ RSA_PRIVATE_ERROR = -218, /* error during rsa priv op */
+ BUILD_MSG_ERROR = -220, /* build message failure */
+
+ BAD_HELLO = -221, /* client hello malformed */
+ DOMAIN_NAME_MISMATCH = -222, /* peer subject name mismatch */
+ WANT_READ = -223, /* want read, call again */
+ NOT_READY_ERROR = -224, /* handshake layer not ready */
+ PMS_VERSION_ERROR = -225, /* pre m secret version error */
+ VERSION_ERROR = -226, /* record layer version error */
+ WANT_WRITE = -227, /* want write, call again */
+ BUFFER_ERROR = -228, /* malformed buffer input */
+ VERIFY_CERT_ERROR = -229, /* verify cert error */
+ VERIFY_SIGN_ERROR = -230, /* verify sign error */
+ CLIENT_ID_ERROR = -231, /* psk client identity error */
+ SERVER_HINT_ERROR = -232, /* psk server hint error */
+ PSK_KEY_ERROR = -233, /* psk key error */
+ ZLIB_INIT_ERROR = -234, /* zlib init error */
+ ZLIB_COMPRESS_ERROR = -235, /* zlib compression error */
+ ZLIB_DECOMPRESS_ERROR = -236, /* zlib decompression error */
+
+ GETTIME_ERROR = -237, /* gettimeofday failed ??? */
+ GETITIMER_ERROR = -238, /* getitimer failed ??? */
+ SIGACT_ERROR = -239, /* sigaction failed ??? */
+ SETITIMER_ERROR = -240, /* setitimer failed ??? */
+ LENGTH_ERROR = -241, /* record layer length error */
+ PEER_KEY_ERROR = -242, /* cant decode peer key */
+ ZERO_RETURN = -243, /* peer sent close notify */
+ SIDE_ERROR = -244, /* wrong client/server type */
+ NO_PEER_CERT = -245, /* peer didn't send key */
+ NTRU_KEY_ERROR = -246, /* NTRU key error */
+ NTRU_DRBG_ERROR = -247, /* NTRU drbg error */
+ NTRU_ENCRYPT_ERROR = -248, /* NTRU encrypt error */
+ NTRU_DECRYPT_ERROR = -249, /* NTRU decrypt error */
+ /* add strings to SetErrorString !!!!! */
+
+ /* begin negotiation parameter errors */
+ UNSUPPORTED_SUITE = -260, /* unsupported cipher suite */
+ MATCH_SUITE_ERROR = -261 /* can't match cipher suite */
+ /* end negotiation parameter errors only 10 for now */
+ /* add strings to SetErrorString !!!!! */
+};
+
+
+#ifdef CYASSL_CALLBACKS
+ enum {
+ MIN_PARAM_ERR = UNSUPPORTED_SUITE,
+ MAX_PARAM_ERR = MIN_PARAM_ERR - 10
+ };
+#endif
+
+
+void SetErrorString(int error, char* buffer);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* CyaSSL_ERROR_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cyassl_int.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,4782 @@
+/* cyassl_int.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#include "asn.h"
+
+#ifdef HAVE_LIBZ
+ #include "zlib.h"
+#endif
+
+#ifdef HAVE_NTRU
+ #include "crypto_ntru.h"
+#endif
+
+#if defined(DEBUG_CYASSL) || defined(SHOW_SECRETS)
+ #include <stdio.h>
+#endif
+
+#ifdef __sun
+ #include <sys/filio.h>
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+
+int CyaSSL_negotiate(SSL*);
+
+
+#ifndef NO_CYASSL_CLIENT
+ static int DoHelloVerifyRequest(SSL* ssl, const byte* input, word32*);
+ static int DoServerHello(SSL* ssl, const byte* input, word32*);
+ static int DoCertificateRequest(SSL* ssl, const byte* input, word32*);
+ static int DoServerKeyExchange(SSL* ssl, const byte* input, word32*);
+#endif
+
+
+#ifndef NO_CYASSL_SERVER
+ static int DoClientHello(SSL* ssl, const byte* input, word32*, word32,
+ word32);
+ static int DoCertificateVerify(SSL* ssl, byte*, word32*, word32);
+ static int DoClientKeyExchange(SSL* ssl, byte* input, word32*);
+#endif
+
+typedef enum {
+ doProcessInit = 0,
+#ifndef NO_CYASSL_SERVER
+ runProcessOldClientHello,
+#endif
+ getRecordLayerHeader,
+ getData,
+ runProcessingOneMessage
+} processReply;
+
+static void Hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify);
+
+static void BuildCertHashes(SSL* ssl, Hashes* hashes);
+
+
+void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender);
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+int IsTLS(const SSL* ssl)
+{
+ if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR)
+ return 1;
+
+ return 0;
+}
+
+
+int IsAtLeastTLSv1_2(const SSL* ssl)
+{
+ if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR)
+ return 1;
+
+ return 0;
+}
+
+
+#ifdef HAVE_NTRU
+
+static byte GetEntropy(ENTROPY_CMD cmd, byte* out)
+{
+ /* TODO: add locking? */
+ static RNG rng;
+
+ if (cmd == INIT) {
+ int ret = InitRng(&rng);
+ if (ret == 0)
+ return 1;
+ else
+ return 0;
+ }
+
+ if (out == NULL)
+ return 0;
+
+ if (cmd == GET_BYTE_OF_ENTROPY) {
+ RNG_GenerateBlock(&rng, out, 1);
+ return 1;
+ }
+
+ if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
+ *out = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif /* HAVE_NTRU */
+
+static INLINE void c32to24(word32 in, word24 out)
+{
+ out[0] = (in >> 16) & 0xff;
+ out[1] = (in >> 8) & 0xff;
+ out[2] = in & 0xff;
+}
+
+
+static INLINE void c32to48(word32 in, byte out[6])
+{
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = (in >> 24) & 0xff;
+ out[3] = (in >> 16) & 0xff;
+ out[4] = (in >> 8) & 0xff;
+ out[5] = in & 0xff;
+}
+
+
+/* convert 16 bit integer to opaque */
+static void INLINE c16toa(word16 u16, byte* c)
+{
+ c[0] = (u16 >> 8) & 0xff;
+ c[1] = u16 & 0xff;
+}
+
+
+/* convert 32 bit integer to opaque */
+static INLINE void c32toa(word32 u32, byte* c)
+{
+ c[0] = (u32 >> 24) & 0xff;
+ c[1] = (u32 >> 16) & 0xff;
+ c[2] = (u32 >> 8) & 0xff;
+ c[3] = u32 & 0xff;
+}
+
+
+/* convert a 24 bit integer into a 32 bit one */
+static INLINE void c24to32(const word24 u24, word32* u32)
+{
+ *u32 = 0;
+ *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
+}
+
+
+/* convert opaque to 16 bit integer */
+static INLINE void ato16(const byte* c, word16* u16)
+{
+ *u16 = 0;
+ *u16 = (c[0] << 8) | (c[1]);
+}
+
+
+/* convert opaque to 32 bit integer */
+static INLINE void ato32(const byte* c, word32* u32)
+{
+ *u32 = 0;
+ *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
+}
+
+
+#ifdef HAVE_LIBZ
+
+ /* alloc user allocs to work with zlib */
+ void* myAlloc(void* opaque, unsigned int item, unsigned int size)
+ {
+ return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ);
+ }
+
+
+ void myFree(void* opaque, void* memory)
+ {
+ XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ);
+ }
+
+
+ /* init zlib comp/decomp streams, 0 on success */
+ static int InitStreams(SSL* ssl)
+ {
+ ssl->c_stream.zalloc = (alloc_func)myAlloc;
+ ssl->c_stream.zfree = (free_func)myFree;
+ ssl->c_stream.opaque = (voidpf)ssl->heap;
+
+ if (deflateInit(&ssl->c_stream, 8) != Z_OK) return ZLIB_INIT_ERROR;
+
+ ssl->didStreamInit = 1;
+
+ ssl->d_stream.zalloc = (alloc_func)myAlloc;
+ ssl->d_stream.zfree = (free_func)myFree;
+ ssl->d_stream.opaque = (voidpf)ssl->heap;
+
+ if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR;
+
+ return 0;
+ }
+
+
+ static void FreeStreams(SSL* ssl)
+ {
+ if (ssl->didStreamInit) {
+ deflateEnd(&ssl->c_stream);
+ inflateEnd(&ssl->d_stream);
+ }
+ }
+
+
+ /* compress in to out, return out size or error */
+ static int Compress(SSL* ssl, byte* in, int inSz, byte* out, int outSz)
+ {
+ int err;
+ int currTotal = ssl->c_stream.total_out;
+
+ /* put size in front of compression */
+ c16toa((word16)inSz, out);
+ out += 2;
+ outSz -= 2;
+
+ ssl->c_stream.next_in = in;
+ ssl->c_stream.avail_in = inSz;
+ ssl->c_stream.next_out = out;
+ ssl->c_stream.avail_out = outSz;
+
+ err = deflate(&ssl->c_stream, Z_SYNC_FLUSH);
+ if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR;
+
+ return ssl->c_stream.total_out - currTotal + sizeof(word16);
+ }
+
+
+ /* decompress in to out, returnn out size or error */
+ static int DeCompress(SSL* ssl, byte* in, int inSz, byte* out, int outSz)
+ {
+ int err;
+ int currTotal = ssl->d_stream.total_out;
+ word16 len;
+
+ /* find size in front of compression */
+ ato16(in, &len);
+ in += 2;
+ inSz -= 2;
+
+ ssl->d_stream.next_in = in;
+ ssl->d_stream.avail_in = inSz;
+ ssl->d_stream.next_out = out;
+ ssl->d_stream.avail_out = outSz;
+
+ err = inflate(&ssl->d_stream, Z_SYNC_FLUSH);
+ if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR;
+
+ return ssl->d_stream.total_out - currTotal;
+ }
+
+#endif /* HAVE_LIBZ */
+
+
+void InitSSL_Method(SSL_METHOD* method, ProtocolVersion pv)
+{
+ method->version = pv;
+ method->side = CLIENT_END;
+ method->verifyPeer = 0;
+ method->verifyNone = 0;
+ method->failNoCert = 0;
+ method->downgrade = 0;
+}
+
+
+void InitSSL_Ctx(SSL_CTX* ctx, SSL_METHOD* method)
+{
+ ctx->method = method;
+ ctx->certificate.buffer = 0;
+ ctx->privateKey.buffer = 0;
+ ctx->haveDH = 0;
+ ctx->haveNTRU = 0; /* start off */
+ ctx->heap = ctx; /* defaults to self */
+#ifndef NO_PSK
+ ctx->havePSK = 0;
+ ctx->server_hint[0] = 0;
+ ctx->client_psk_cb = 0;
+ ctx->server_psk_cb = 0;
+#endif /* NO_PSK */
+
+#ifdef OPENSSL_EXTRA
+ ctx->passwd_cb = 0;
+ ctx->userdata = 0;
+#endif /* OPENSSL_EXTRA */
+
+#ifndef CYASSL_USER_IO
+ ctx->CBIORecv = EmbedReceive;
+ ctx->CBIOSend = EmbedSend;
+#else
+ /* user will set */
+ ctx->CBIORecv = NULL;
+ ctx->CBIOSend = NULL;
+#endif
+ ctx->partialWrite = 0;
+ ctx->verifyCallback = 0;
+
+ ctx->caList = 0;
+#ifdef HAVE_NTRU
+ if (method->side == CLIENT_END)
+ ctx->haveNTRU = 1; /* always on cliet side */
+ /* server can turn on by loading key */
+#endif
+ /* remove DH later if server didn't set, add psk later */
+ InitSuites(&ctx->suites, method->version, TRUE, FALSE, ctx->haveNTRU);
+ ctx->verifyPeer = 0;
+ ctx->verifyNone = 0;
+ ctx->failNoCert = 0;
+ ctx->sessionCacheOff = 0; /* initially on */
+ ctx->sessionCacheFlushOff = 0; /* initially on */
+ ctx->sendVerify = 0;
+ ctx->quietShutdown = 0;
+
+}
+
+
+/* In case contexts are held in array and don't want to free actual ctx */
+void SSL_CtxResourceFree(SSL_CTX* ctx)
+{
+ XFREE(ctx->privateKey.buffer, ctx->heap, DYNAMIC_TYPE_KEY);
+ XFREE(ctx->certificate.buffer, ctx->heap, DYNAMIC_TYPE_CERT);
+ XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD);
+
+ FreeSigners(ctx->caList, ctx->heap);
+}
+
+
+void FreeSSL_Ctx(SSL_CTX* ctx)
+{
+ SSL_CtxResourceFree(ctx);
+ XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX);
+}
+
+
+
+void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK,
+ byte haveNTRU)
+{
+ word32 idx = 0;
+ int tls = pv.major == 3 && pv.minor >= 1;
+
+ (void)tls; /* shut up compiler */
+
+#ifdef CYASSL_DTLS
+ if (pv.major == DTLS_MAJOR && pv.minor == DTLS_MINOR)
+ tls = 1;
+#endif
+
+ suites->setSuites = 0; /* user hasn't set yet */
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ if (tls && haveNTRU) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ if (tls && haveNTRU) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ if (tls && haveNTRU) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ if (tls && haveNTRU) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ if (tls && haveDH) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ if (tls && haveDH) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ if (tls) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ if (tls) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ if (tls && havePSK) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ if (tls && havePSK) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ if (tls) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_MD5;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ if (tls) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_HC_128_CBC_SHA;
+ }
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ if (tls) {
+ suites->suites[idx++] = 0;
+ suites->suites[idx++] = TLS_RSA_WITH_RABBIT_CBC_SHA;
+ }
+#endif
+
+ suites->suiteSz = idx;
+}
+
+
+int InitSSL(SSL* ssl, SSL_CTX* ctx)
+{
+ int ret;
+ byte havePSK = 0;
+
+ ssl->ctx = ctx; /* only for passing to calls, options could change */
+ ssl->version = ctx->method->version;
+ ssl->suites = ctx->suites;
+
+#ifdef HAVE_LIBZ
+ ssl->didStreamInit = 0;
+#endif
+
+ ssl->buffers.certificate.buffer = 0;
+ ssl->buffers.key.buffer = 0;
+ ssl->buffers.inputBuffer.length = 0;
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+ ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.inputBuffer.dynamicFlag = 0;
+ ssl->buffers.outputBuffer.length = 0;
+ ssl->buffers.outputBuffer.idx = 0;
+ ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+ ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.outputBuffer.dynamicFlag = 0;
+ ssl->buffers.domainName.buffer = 0;
+ ssl->buffers.serverDH_P.buffer = 0;
+ ssl->buffers.serverDH_G.buffer = 0;
+ ssl->buffers.serverDH_Pub.buffer = 0;
+ ssl->buffers.serverDH_Priv.buffer = 0;
+ ssl->buffers.clearOutputBuffer.buffer = 0;
+ ssl->buffers.clearOutputBuffer.length = 0;
+ ssl->buffers.prevSent = 0;
+ ssl->buffers.plainSz = 0;
+
+ if ( (ret = InitRng(&ssl->rng)) )
+ return ret;
+
+ InitMd5(&ssl->hashMd5);
+ InitSha(&ssl->hashSha);
+ InitRsaKey(&ssl->peerRsaKey, ctx->heap);
+
+ ssl->peerRsaKeyPresent = 0;
+ ssl->options.side = ctx->method->side;
+ ssl->options.downgrade = ctx->method->downgrade;
+ ssl->error = 0;
+ ssl->options.connReset = 0;
+ ssl->options.isClosed = 0;
+ ssl->options.closeNotify = 0;
+ ssl->options.sentNotify = 0;
+ ssl->options.usingCompression = 0;
+ ssl->options.haveDH = ctx->haveDH;
+ ssl->options.haveNTRU = ctx->haveNTRU;
+ ssl->options.havePeerCert = 0;
+ ssl->options.usingPSK_cipher = 0;
+ ssl->options.sendAlertState = 0;
+#ifndef NO_PSK
+ havePSK = ctx->havePSK;
+ ssl->options.havePSK = ctx->havePSK;
+ ssl->options.client_psk_cb = ctx->client_psk_cb;
+ ssl->options.server_psk_cb = ctx->server_psk_cb;
+#endif /* NO_PSK */
+
+ ssl->options.serverState = NULL_STATE;
+ ssl->options.clientState = NULL_STATE;
+ ssl->options.connectState = CONNECT_BEGIN;
+ ssl->options.acceptState = ACCEPT_BEGIN;
+ ssl->options.handShakeState = NULL_STATE;
+ ssl->options.processReply = doProcessInit;
+
+#ifdef CYASSL_DTLS
+ ssl->keys.dtls_sequence_number = 0;
+ ssl->keys.dtls_peer_sequence_number = 0;
+ ssl->keys.dtls_handshake_number = 0;
+ ssl->keys.dtls_epoch = 0;
+ ssl->keys.dtls_peer_epoch = 0;
+#endif
+ ssl->keys.encryptionOn = 0; /* initially off */
+ ssl->options.sessionCacheOff = ctx->sessionCacheOff;
+ ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff;
+
+ ssl->options.verifyPeer = ctx->verifyPeer;
+ ssl->options.verifyNone = ctx->verifyNone;
+ ssl->options.failNoCert = ctx->failNoCert;
+ ssl->options.sendVerify = ctx->sendVerify;
+
+ ssl->options.resuming = 0;
+ ssl->hmac = Hmac; /* default to SSLv3 */
+ ssl->heap = ctx->heap; /* defaults to self */
+ ssl->options.tls = 0;
+ ssl->options.tls1_1 = 0;
+ ssl->options.dtls = 0;
+ ssl->options.partialWrite = ctx->partialWrite;
+ ssl->options.quietShutdown = ctx->quietShutdown;
+
+ /* SSL_CTX still owns certificate, key, and caList buffers */
+ ssl->buffers.certificate = ctx->certificate;
+ ssl->buffers.key = ctx->privateKey;
+ ssl->caList = ctx->caList;
+
+#ifdef OPENSSL_EXTRA
+ ssl->peerCert.issuer.sz = 0;
+ ssl->peerCert.subject.sz = 0;
+#endif
+
+ /* make sure server has cert and key unless using PSK */
+ if (ssl->options.side == SERVER_END && !havePSK)
+ if (!ssl->buffers.certificate.buffer || !ssl->buffers.key.buffer)
+ return NO_PRIVATE_KEY;
+
+#ifndef NO_PSK
+ ssl->arrays.client_identity[0] = 0;
+ if (ctx->server_hint[0]) /* set in CTX */
+ XSTRNCPY(ssl->arrays.server_hint, ctx->server_hint, MAX_PSK_ID_LEN);
+ else
+ ssl->arrays.server_hint[0] = 0;
+#endif /* NO_PSK */
+
+#ifdef CYASSL_CALLBACKS
+ ssl->hsInfoOn = 0;
+ ssl->toInfoOn = 0;
+#endif
+
+ /* make sure server has DH parms, and add PSK if there, add NTRU too */
+ if (!ssl->ctx->suites.setSuites) { /* trust user override */
+ if (ssl->options.side == SERVER_END)
+ InitSuites(&ssl->suites, ssl->version,ssl->options.haveDH, havePSK,
+ ssl->options.haveNTRU);
+ else
+ InitSuites(&ssl->suites, ssl->version, TRUE, havePSK,
+ ssl->options.haveNTRU);
+ }
+
+ ssl->rfd = -1; /* set to invalid descriptor */
+ ssl->wfd = -1;
+ ssl->biord = 0;
+ ssl->biowr = 0;
+
+ ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer acess if not */
+ ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */
+
+#ifdef SESSION_CERTS
+ ssl->session.chain.count = 0;
+#endif
+
+ ssl->cipher.ssl = ssl;
+
+ return 0;
+}
+
+
+int BIO_free(BIO*); /* cyassl_int doesn't have */
+
+
+/* In case holding SSL object in array and don't want to free actual ssl */
+void SSL_ResourceFree(SSL* ssl)
+{
+ XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH);
+ XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+ FreeRsaKey(&ssl->peerRsaKey);
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, FORCED_FREE);
+ if (ssl->buffers.outputBuffer.dynamicFlag)
+ ShrinkOutputBuffer(ssl);
+#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
+ BIO_free(ssl->biord);
+ if (ssl->biord != ssl->biowr) /* in case same as write */
+ BIO_free(ssl->biowr);
+#endif
+#ifdef HAVE_LIBZ
+ FreeStreams(ssl);
+#endif
+}
+
+
+void FreeSSL(SSL* ssl)
+{
+ SSL_ResourceFree(ssl);
+ XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL);
+}
+
+
+ProtocolVersion MakeSSLv3(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = SSLv3_MINOR;
+
+ return pv;
+}
+
+
+#ifdef CYASSL_DTLS
+
+ProtocolVersion MakeDTLSv1(void)
+{
+ ProtocolVersion pv;
+ pv.major = DTLS_MAJOR;
+ pv.minor = DTLS_MINOR;
+
+ return pv;
+}
+
+#endif /* CYASSL_DTLS */
+
+
+
+
+#ifdef USE_WINDOWS_API
+
+ timer_d Timer(void)
+ {
+ static int init = 0;
+ static LARGE_INTEGER freq;
+ LARGE_INTEGER count;
+
+ if (!init) {
+ QueryPerformanceFrequency(&freq);
+ init = 1;
+ }
+
+ QueryPerformanceCounter(&count);
+
+ return (double)count.QuadPart / freq.QuadPart;
+ }
+
+
+ word32 LowResTimer(void)
+ {
+ return (word32)Timer();
+ }
+
+
+#elif defined(THREADX)
+
+ #include "rtptime.h"
+
+ word32 LowResTimer(void)
+ {
+ return (word32)rtp_get_system_sec();
+ }
+
+
+#elif defined(MICRIUM)
+
+ word32 LowResTimer(void)
+ {
+ NET_SECURE_OS_TICK clk;
+
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ clk = NetSecure_OS_TimeGet();
+ #endif
+ return (word32)clk;
+ }
+
+#elif defined(USER_TICKS)
+
+ word32 LowResTimer(void)
+ {
+ /*
+ write your own clock tick function if don't want time(0)
+ needs second accuracy but doesn't have to correlated to EPOCH
+ */
+ }
+
+#else /* !USE_WINDOWS_API && !THREADX && !MICRIUM && !USER_TICKS */
+
+ #include <time.h>
+
+ word32 LowResTimer(void)
+ {
+ return time(0);
+ }
+
+
+#endif /* USE_WINDOWS_API */
+
+
+/* add output to md5 and sha handshake hashes, exclude record header */
+static void HashOutput(SSL* ssl, const byte* output, int sz, int ivSz)
+{
+ const byte* buffer = output + RECORD_HEADER_SZ + ivSz;
+ sz -= RECORD_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ buffer += DTLS_RECORD_EXTRA;
+ sz -= DTLS_RECORD_EXTRA;
+ }
+#endif
+
+ Md5Update(&ssl->hashMd5, buffer, sz);
+ ShaUpdate(&ssl->hashSha, buffer, sz);
+}
+
+
+/* add input to md5 and sha handshake hashes, include handshake header */
+static void HashInput(SSL* ssl, const byte* input, int sz)
+{
+ const byte* buffer = input - HANDSHAKE_HEADER_SZ;
+ sz += HANDSHAKE_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ buffer -= DTLS_HANDSHAKE_EXTRA;
+ sz += DTLS_HANDSHAKE_EXTRA;
+ }
+#endif
+
+ Md5Update(&ssl->hashMd5, buffer, sz);
+ ShaUpdate(&ssl->hashSha, buffer, sz);
+}
+
+
+/* add record layer header for message */
+static void AddRecordHeader(byte* output, word32 length, byte type, SSL* ssl)
+{
+ RecordLayerHeader* rl;
+
+ /* record layer header */
+ rl = (RecordLayerHeader*)output;
+ rl->type = type;
+ rl->version = ssl->version; /* type and version same in each */
+
+ if (!ssl->options.dtls)
+ c16toa((word16)length, rl->length);
+ else {
+#ifdef CYASSL_DTLS
+ DtlsRecordLayerHeader* dtls;
+
+ /* dtls record layer header extensions */
+ dtls = (DtlsRecordLayerHeader*)output;
+ c16toa(ssl->keys.dtls_epoch, dtls->epoch);
+ c32to48(ssl->keys.dtls_sequence_number++, dtls->sequence_number);
+ c16toa((word16)length, dtls->length);
+#endif
+ }
+}
+
+
+/* add handshake header for message */
+static void AddHandShakeHeader(byte* output, word32 length, byte type, SSL* ssl)
+{
+ HandShakeHeader* hs;
+
+ /* handshake header */
+ hs = (HandShakeHeader*)output;
+ hs->type = type;
+ c32to24(length, hs->length); /* type and length same for each */
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ DtlsHandShakeHeader* dtls;
+
+ /* dtls handshake header extensions */
+ dtls = (DtlsHandShakeHeader*)output;
+ c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq);
+ c32to24(0, dtls->fragment_offset);
+ c32to24(length, dtls->fragment_length);
+ }
+#endif
+}
+
+
+/* add both headers for handshake message */
+static void AddHeaders(byte* output, word32 length, byte type, SSL* ssl)
+{
+ if (!ssl->options.dtls) {
+ AddRecordHeader(output, length + HANDSHAKE_HEADER_SZ, handshake, ssl);
+ AddHandShakeHeader(output + RECORD_HEADER_SZ, length, type, ssl);
+ }
+ else {
+ AddRecordHeader(output, length+DTLS_HANDSHAKE_HEADER_SZ, handshake,ssl);
+ AddHandShakeHeader(output + DTLS_RECORD_HEADER_SZ, length, type, ssl);
+ }
+}
+
+
+static int Receive(SSL* ssl, byte* buf, word32 sz, int flags)
+{
+ int recvd;
+
+retry:
+ recvd = ssl->ctx->CBIORecv((char *)buf, (int)sz, ssl->IOCB_ReadCtx);
+ if (recvd < 0)
+ switch (recvd) {
+ case IO_ERR_GENERAL: /* general/unknown error */
+ return -1;
+
+ case IO_ERR_WANT_READ: /* want read, would block */
+ return WANT_READ;
+
+ case IO_ERR_CONN_RST: /* connection reset */
+ ssl->options.connReset = 1;
+ return -1;
+
+ case IO_ERR_ISR: /* interrupt */
+ /* see if we got our timeout */
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->toInfoOn) {
+ struct itimerval timeout;
+ getitimer(ITIMER_REAL, &timeout);
+ if (timeout.it_value.tv_sec == 0 &&
+ timeout.it_value.tv_usec == 0) {
+ XSTRNCPY(ssl->timeoutInfo.timeoutName,
+ "recv() timeout", MAX_TIMEOUT_NAME_SZ);
+ return 0;
+ }
+ }
+ #endif
+ goto retry;
+
+ case IO_ERR_CONN_CLOSE: /* peer closed connection */
+ ssl->options.isClosed = 1;
+ return -1;
+ }
+
+ return recvd;
+}
+
+
+/* Switch dynamic output buffer back to static, buffer is assumed clear */
+void ShrinkOutputBuffer(SSL* ssl)
+{
+ CYASSL_MSG("Shrinking output buffer\n");
+ XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+ ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer;
+ ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.outputBuffer.dynamicFlag = 0;
+}
+
+
+/* Switch dynamic input buffer back to static, keep any remaining input */
+/* forced free means cleaning up */
+void ShrinkInputBuffer(SSL* ssl, int forcedFree)
+{
+ int usedLength = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (!forcedFree && usedLength > STATIC_BUFFER_LEN)
+ return;
+
+ CYASSL_MSG("Shrinking input buffer\n");
+
+ if (!forcedFree && usedLength)
+ XMEMCPY(ssl->buffers.inputBuffer.staticBuffer,
+ ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+ usedLength);
+
+ XFREE(ssl->buffers.inputBuffer.buffer, ssl->heap, DYNAMIC_TYPE_IN_BUFFER);
+ ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer;
+ ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN;
+ ssl->buffers.inputBuffer.dynamicFlag = 0;
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.length = usedLength;
+}
+
+
+int SendBuffered(SSL* ssl)
+{
+ while (ssl->buffers.outputBuffer.length > 0) {
+ int sent = ssl->ctx->CBIOSend((char*)ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx,
+ (int)ssl->buffers.outputBuffer.length,
+ ssl->IOCB_WriteCtx);
+ if (sent < 0) {
+ switch (sent) {
+
+ case IO_ERR_WANT_WRITE: /* would block */
+ return WANT_WRITE;
+
+ case IO_ERR_CONN_RST: /* connection reset */
+ ssl->options.connReset = 1;
+ break;
+
+ case IO_ERR_ISR: /* interrupt */
+ /* see if we got our timeout */
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->toInfoOn) {
+ struct itimerval timeout;
+ getitimer(ITIMER_REAL, &timeout);
+ if (timeout.it_value.tv_sec == 0 &&
+ timeout.it_value.tv_usec == 0) {
+ XSTRNCPY(ssl->timeoutInfo.timeoutName,
+ "send() timeout", MAX_TIMEOUT_NAME_SZ);
+ return WANT_WRITE;
+ }
+ }
+ #endif
+ continue;
+
+ case IO_ERR_CONN_CLOSE: /* epipe / conn closed, same as reset */
+ ssl->options.connReset = 1;
+ break;
+ }
+
+ return SOCKET_ERROR_E;
+ }
+
+ ssl->buffers.outputBuffer.idx += sent;
+ ssl->buffers.outputBuffer.length -= sent;
+ }
+
+ ssl->buffers.outputBuffer.idx = 0;
+
+ if (ssl->buffers.outputBuffer.dynamicFlag)
+ ShrinkOutputBuffer(ssl);
+
+ return 0;
+}
+
+
+/* Grow the output buffer, should only be to send cert, should be blank */
+static INLINE int GrowOutputBuffer(SSL* ssl, int size)
+{
+ byte* tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length,
+ ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
+ CYASSL_MSG("growing output buffer\n");
+
+ if (!tmp) return -1;
+
+ if (ssl->buffers.outputBuffer.length)
+ XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer,
+ ssl->buffers.outputBuffer.length);
+
+ if (ssl->buffers.outputBuffer.dynamicFlag)
+ XFREE(ssl->buffers.outputBuffer.buffer, ssl->heap,
+ DYNAMIC_TYPE_OUT_BUFFER);
+ ssl->buffers.outputBuffer.dynamicFlag = 1;
+ ssl->buffers.outputBuffer.buffer = tmp;
+ ssl->buffers.outputBuffer.bufferSize = size +
+ ssl->buffers.outputBuffer.length;
+ return 0;
+}
+
+
+/* Grow the input buffer, should only be to read cert or big app data */
+static INLINE int GrowInputBuffer(SSL* ssl, int size, int usedLength)
+{
+ byte* tmp = (byte*) XMALLOC(size + usedLength, ssl->heap,
+ DYNAMIC_TYPE_IN_BUFFER);
+ CYASSL_MSG("growing input buffer\n");
+
+ if (!tmp) return -1;
+
+ if (usedLength)
+ XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.idx, usedLength);
+
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ XFREE(ssl->buffers.inputBuffer.buffer,ssl->heap,DYNAMIC_TYPE_IN_BUFFER);
+
+ ssl->buffers.inputBuffer.dynamicFlag = 1;
+ ssl->buffers.inputBuffer.buffer = tmp;
+ ssl->buffers.inputBuffer.bufferSize = size + usedLength;
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.length = usedLength;
+
+ return 0;
+}
+
+
+/* check avalaible size into outbut buffer */
+static INLINE int CheckAvalaibleSize(SSL *ssl, int size)
+{
+ if ((word32)size > ssl->buffers.outputBuffer.bufferSize)
+ if (GrowOutputBuffer(ssl, size) < 0)
+ return MEMORY_E;
+
+ if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length
+ < (word32)size) {
+ if (SendBuffered(ssl) == SOCKET_ERROR_E)
+ return SOCKET_ERROR_E;
+ if (ssl->buffers.outputBuffer.bufferSize -
+ ssl->buffers.outputBuffer.length < (word32)size)
+ return WANT_WRITE;
+ }
+ return 0;
+}
+
+/* do all verify and sanity checks on record header */
+static int GetRecordHeader(SSL* ssl, const byte* input, word32* inOutIdx,
+ RecordLayerHeader* rh, word16 *size)
+{
+ if (!ssl->options.dtls) {
+ XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ);
+ *inOutIdx += RECORD_HEADER_SZ;
+ ato16(rh->length, size);
+ }
+ else {
+#ifdef CYASSL_DTLS
+ /* type and version in same sport */
+ XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ);
+ *inOutIdx += ENUM_LEN + VERSION_SZ;
+ *inOutIdx += 4; /* skip epoch and first 2 seq bytes for now */
+ ato32(input + *inOutIdx, &ssl->keys.dtls_peer_sequence_number);
+ *inOutIdx += 4; /* advance past rest of seq */
+ ato16(input + *inOutIdx, size);
+ *inOutIdx += LENGTH_SZ;
+#endif
+ }
+
+ /* catch version mismatch */
+ if (rh->version.major != ssl->version.major ||
+ rh->version.minor != ssl->version.minor) {
+
+ if (ssl->options.side == SERVER_END && ssl->options.downgrade == 1 &&
+ ssl->options.acceptState == ACCEPT_BEGIN)
+ ; /* haven't negotiated yet */
+ else
+ return VERSION_ERROR; /* only use requested version */
+ }
+
+ /* record layer length check */
+ if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA))
+ return LENGTH_ERROR;
+
+ /* verify record type here as well */
+ switch ((enum ContentType)rh->type) {
+ case handshake:
+ case change_cipher_spec:
+ case application_data:
+ case alert:
+ break;
+ default:
+ return UNKNOWN_RECORD_TYPE;
+ }
+
+ return 0;
+}
+
+
+static int GetHandShakeHeader(SSL* ssl, const byte* input, word32* inOutIdx,
+ byte *type, word32 *size)
+{
+ const byte *ptr = input + *inOutIdx;
+ *inOutIdx += HANDSHAKE_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ *inOutIdx += DTLS_HANDSHAKE_EXTRA;
+#endif
+
+ *type = ptr[0];
+ c24to32(&ptr[1], size);
+
+ return 0;
+}
+
+
+/* fill with MD5 pad size since biggest required */
+static const byte PAD1[PAD_MD5] =
+ { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+ };
+static const byte PAD2[PAD_MD5] =
+ { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+ 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+ };
+
+/* calculate MD5 hash for finished */
+static void BuildMD5(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ byte md5_result[MD5_DIGEST_SIZE];
+
+ /* make md5 inner */
+ Md5Update(&ssl->hashMd5, sender, SIZEOF_SENDER);
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
+ Md5Final(&ssl->hashMd5, md5_result);
+
+ /* make md5 outer */
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
+ Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
+
+ Md5Final(&ssl->hashMd5, hashes->md5);
+}
+
+
+/* calculate SHA hash for finished */
+static void BuildSHA(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ byte sha_result[SHA_DIGEST_SIZE];
+
+ /* make sha inner */
+ ShaUpdate(&ssl->hashSha, sender, SIZEOF_SENDER);
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
+ ShaFinal(&ssl->hashSha, sha_result);
+
+ /* make sha outer */
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
+ ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
+
+ ShaFinal(&ssl->hashSha, hashes->sha);
+}
+
+
+static void BuildFinished(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ /* store current states, building requires get_digest which resets state */
+ Md5 md5 = ssl->hashMd5;
+ Sha sha = ssl->hashSha;
+
+ if (ssl->options.tls)
+ BuildTlsFinished(ssl, hashes, sender);
+ else {
+ BuildMD5(ssl, hashes, sender);
+ BuildSHA(ssl, hashes, sender);
+ }
+
+ /* restore */
+ ssl->hashMd5 = md5;
+ ssl->hashSha = sha;
+}
+
+
+static int DoCertificate(SSL* ssl, byte* input, word32* inOutIdx)
+{
+ word32 listSz, i = *inOutIdx;
+ int ret = 0;
+ int firstTime = 1; /* peer's is at front */
+ char domain[ASN_NAME_MAX];
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo);
+ #endif
+ c24to32(&input[i], &listSz);
+ i += CERT_HEADER_SZ;
+
+ while (listSz && ret == 0) {
+ /* cert size */
+ buffer myCert;
+ word32 certSz;
+ DecodedCert dCert;
+ word32 idx = 0;
+
+ c24to32(&input[i], &certSz);
+ i += CERT_HEADER_SZ;
+
+ myCert.length = certSz;
+ myCert.buffer = input + i;
+ i += certSz;
+
+ listSz -= certSz + CERT_HEADER_SZ;
+
+#ifdef SESSION_CERTS
+ if (ssl->session.chain.count < MAX_CHAIN_DEPTH &&
+ myCert.length < MAX_X509_SIZE) {
+ ssl->session.chain.certs[ssl->session.chain.count].length =
+ myCert.length;
+ XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer,
+ myCert.buffer, myCert.length);
+ ssl->session.chain.count++;
+ } else {
+ CYASSL_MSG("Couldn't store chain cert for session");
+ }
+#endif
+
+ InitDecodedCert(&dCert, myCert.buffer, ssl->heap);
+ ret = ParseCertRelative(&dCert, myCert.length, CERT_TYPE,
+ !ssl->options.verifyNone, ssl->caList);
+
+ if (!firstTime) {
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+
+ /* get rest of peer info in case user wants to continue */
+ if (ret != 0) {
+ if (!(ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E ||
+ ret == ASN_SIG_CONFIRM_E)) {
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+ }
+
+ /* first one has peer's key */
+ firstTime = 0;
+
+ ssl->options.havePeerCert = 1;
+ /* set X509 format */
+#ifdef OPENSSL_EXTRA
+ ssl->peerCert.issuer.sz = (int)XSTRLEN(dCert.issuer) + 1;
+ XSTRNCPY(ssl->peerCert.issuer.name, dCert.issuer, ASN_NAME_MAX);
+ ssl->peerCert.subject.sz = (int)XSTRLEN(dCert.subject) + 1;
+ XSTRNCPY(ssl->peerCert.subject.name, dCert.subject, ASN_NAME_MAX);
+#endif
+
+ XMEMCPY(domain, dCert.subjectCN, dCert.subjectCNLen);
+ domain[dCert.subjectCNLen] = '\0';
+
+ if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer)
+ if (XSTRNCMP((char*)ssl->buffers.domainName.buffer,
+ dCert.subjectCN,
+ ssl->buffers.domainName.length - 1)) {
+ ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */
+ }
+
+ /* decode peer key */
+ if (dCert.keyOID == RSAk) {
+ if (RsaPublicKeyDecode(dCert.publicKey, &idx,
+ &ssl->peerRsaKey, dCert.pubKeySize) != 0) {
+ ret = PEER_KEY_ERROR;
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+ ssl->peerRsaKeyPresent = 1;
+ }
+#ifdef HAVE_NTRU
+ else if (dCert.keyOID == NTRUk) {
+ if (dCert.pubKeySize > sizeof(ssl->peerNtruKey)) {
+ ret = PEER_KEY_ERROR;
+ FreeDecodedCert(&dCert);
+ continue;
+ }
+ XMEMCPY(ssl->peerNtruKey, dCert.publicKey, dCert.pubKeySize);
+ ssl->peerNtruKeyLen = (word16)dCert.pubKeySize;
+ ssl->peerNtruKeyPresent = 1;
+ }
+#endif
+
+ FreeDecodedCert(&dCert);
+ }
+
+ if (ret == 0 && ssl->options.side == CLIENT_END)
+ ssl->options.serverState = SERVER_CERT_COMPLETE;
+
+ if (ret != 0) {
+ if (!ssl->options.verifyNone) {
+ int why = bad_certificate;
+ if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E)
+ why = certificate_expired;
+ if (ssl->ctx->verifyCallback) {
+ int ok;
+ X509_STORE_CTX store;
+
+ store.error = ret;
+ store.error_depth = 1;
+ store.domain = domain;
+#ifdef OPENSSL_EXTRA
+ store.current_cert = &ssl->peerCert;
+#else
+ store.current_cert = NULL;
+#endif
+ ok = ssl->ctx->verifyCallback(0, &store);
+ if (ok)
+ ret = 0;
+ }
+ if (ret != 0) {
+ SendAlert(ssl, alert_fatal, why); /* try to send */
+ ssl->options.isClosed = 1;
+ }
+ }
+ ssl->error = ret;
+ }
+
+ *inOutIdx = i;
+ return ret;
+}
+
+
+int DoFinished(SSL* ssl, const byte* input, word32* inOutIdx, int sniff)
+{
+ byte verifyMAC[SHA_DIGEST_SIZE];
+ int finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ;
+ int headerSz = HANDSHAKE_HEADER_SZ;
+ word32 macSz = finishedSz + HANDSHAKE_HEADER_SZ,
+ idx = *inOutIdx,
+ padSz = ssl->keys.encryptSz - HANDSHAKE_HEADER_SZ - finishedSz -
+ ssl->specs.hash_size;
+ const byte* mac;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ headerSz += DTLS_HANDSHAKE_EXTRA;
+ macSz += DTLS_HANDSHAKE_EXTRA;
+ padSz -= DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo);
+ #endif
+ if (sniff == NO_SNIFF) {
+ if (XMEMCMP(input + idx, &ssl->verifyHashes, finishedSz))
+ return VERIFY_FINISHED_ERROR;
+ }
+
+ ssl->hmac(ssl, verifyMAC, input + idx - headerSz, macSz,
+ handshake, 1);
+ idx += finishedSz;
+
+ /* read mac and fill */
+ mac = input + idx;
+ idx += ssl->specs.hash_size;
+
+ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+ padSz -= ssl->specs.block_size;
+
+ idx += padSz;
+
+ /* verify mac */
+ if (XMEMCMP(mac, verifyMAC, ssl->specs.hash_size))
+ return VERIFY_MAC_ERROR;
+
+ if (ssl->options.side == CLIENT_END) {
+ ssl->options.serverState = SERVER_FINISHED_COMPLETE;
+ if (!ssl->options.resuming)
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ }
+ else {
+ ssl->options.clientState = CLIENT_FINISHED_COMPLETE;
+ if (ssl->options.resuming)
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ }
+
+ *inOutIdx = idx;
+ return 0;
+}
+
+
+static int DoHandShakeMsg(SSL* ssl, byte* input, word32* inOutIdx,
+ word32 totalSz)
+{
+ byte type;
+ word32 size;
+ int ret = 0;
+
+ CYASSL_ENTER("DoHandShakeMsg()");
+
+ if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size) != 0)
+ return PARSE_ERROR;
+
+ if (*inOutIdx + size > totalSz)
+ return INCOMPLETE_DATA;
+
+ HashInput(ssl, input + *inOutIdx, size);
+#ifdef CYASSL_CALLBACKS
+ /* add name later, add on record and handshake header part back on */
+ if (ssl->toInfoOn) {
+ int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add,
+ size + add, ssl->heap);
+ AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+ }
+#endif
+
+ switch (type) {
+
+#ifndef NO_CYASSL_CLIENT
+ case hello_verify_request:
+ CYASSL_MSG("processing hello verify request");
+ ret = DoHelloVerifyRequest(ssl, input,inOutIdx);
+ break;
+
+ case server_hello:
+ CYASSL_MSG("processing server hello");
+ ret = DoServerHello(ssl, input, inOutIdx);
+ break;
+
+ case certificate_request:
+ CYASSL_MSG("processing certificate request");
+ ret = DoCertificateRequest(ssl, input, inOutIdx);
+ break;
+
+ case server_key_exchange:
+ CYASSL_MSG("processing server key exchange");
+ ret = DoServerKeyExchange(ssl, input, inOutIdx);
+ break;
+#endif
+
+ case certificate:
+ CYASSL_MSG("processing certificate");
+ ret = DoCertificate(ssl, input, inOutIdx);
+ break;
+
+ case server_hello_done:
+ CYASSL_MSG("processing server hello done");
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ServerHelloDone", &ssl->timeoutInfo);
+ #endif
+ ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+ break;
+
+ case finished:
+ CYASSL_MSG("processing finished");
+ ret = DoFinished(ssl, input, inOutIdx, NO_SNIFF);
+ break;
+
+#ifndef NO_CYASSL_SERVER
+ case client_hello:
+ CYASSL_MSG("processing client hello");
+ ret = DoClientHello(ssl, input, inOutIdx, totalSz, size);
+ break;
+
+ case client_key_exchange:
+ CYASSL_MSG("processing client key exchange");
+ ret = DoClientKeyExchange(ssl, input, inOutIdx);
+ break;
+
+ case certificate_verify:
+ CYASSL_MSG("processing certificate verify");
+ ret = DoCertificateVerify(ssl, input, inOutIdx, totalSz);
+ break;
+
+#endif
+
+ default:
+ ret = UNKNOWN_HANDSHAKE_TYPE;
+ }
+
+ CYASSL_LEAVE("DoHandShakeMsg()", ret);
+ return ret;
+}
+
+
+static INLINE void Encrypt(SSL* ssl, byte* out, const byte* input, word32 sz)
+{
+ switch (ssl->specs.bulk_cipher_algorithm) {
+ #ifdef BUILD_ARC4
+ case rc4:
+ Arc4Process(&ssl->encrypt.arc4, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_DES3
+ case triple_des:
+ Des3_CbcEncrypt(&ssl->encrypt.des3, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_AES
+ case aes:
+#ifdef CYASSL_AESNI
+ if ((word)input % 16) {
+ byte buffer[MAX_RECORD_SIZE + MAX_COMP_EXTRA+MAX_MSG_EXTRA];
+ XMEMCPY(buffer, input, sz);
+ AesCbcEncrypt(&ssl->encrypt.aes, buffer, buffer, sz);
+ XMEMCPY(out, buffer, sz);
+ break;
+ }
+#endif
+ AesCbcEncrypt(&ssl->encrypt.aes, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_HC128
+ case hc128:
+ Hc128_Process(&ssl->encrypt.hc128, out, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_RABBIT
+ case rabbit:
+ RabbitProcess(&ssl->encrypt.rabbit, out, input, sz);
+ break;
+ #endif
+ }
+}
+
+
+static INLINE void Decrypt(SSL* ssl, byte* plain, const byte* input, word32 sz)
+{
+ switch (ssl->specs.bulk_cipher_algorithm) {
+ #ifdef BUILD_ARC4
+ case rc4:
+ Arc4Process(&ssl->decrypt.arc4, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_DES3
+ case triple_des:
+ Des3_CbcDecrypt(&ssl->decrypt.des3, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_AES
+ case aes:
+ AesCbcDecrypt(&ssl->decrypt.aes, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_HC128
+ case hc128:
+ Hc128_Process(&ssl->decrypt.hc128, plain, input, sz);
+ break;
+ #endif
+
+ #ifdef BUILD_RABBIT
+ case rabbit:
+ RabbitProcess(&ssl->decrypt.rabbit, plain, input, sz);
+ break;
+ #endif
+ }
+}
+
+
+/* decrypt input message in place */
+static int DecryptMessage(SSL* ssl, byte* input, word32 sz, word32* idx)
+{
+ Decrypt(ssl, input, input, sz);
+ ssl->keys.encryptSz = sz;
+ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
+ *idx += ssl->specs.block_size; /* go past TLSv1.1 IV */
+
+ return 0;
+}
+
+
+static INLINE word32 GetSEQIncrement(SSL* ssl, int verify)
+{
+ if (verify)
+ return ssl->keys.peer_sequence_number++;
+ else
+ return ssl->keys.sequence_number++;
+}
+
+
+int DoApplicationData(SSL* ssl, byte* input, word32* inOutIdx)
+{
+ word32 msgSz = ssl->keys.encryptSz;
+ word32 pad = 0,
+ padByte = 0,
+ idx = *inOutIdx,
+ digestSz = ssl->specs.hash_size;
+ int dataSz;
+ int ivExtra = 0;
+ byte* rawData = input + idx; /* keep current for hmac */
+#ifdef HAVE_LIBZ
+ byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+#endif
+
+ byte verify[SHA_DIGEST_SIZE];
+ const byte* mac;
+
+ if (ssl->specs.cipher_type == block) {
+ if (ssl->options.tls1_1)
+ ivExtra = ssl->specs.block_size;
+ pad = *(input + idx + msgSz - ivExtra - 1);
+ padByte = 1;
+ }
+
+ dataSz = msgSz - ivExtra - digestSz - pad - padByte;
+ if (dataSz < 0)
+ return BUFFER_ERROR;
+
+ /* read data */
+ if (dataSz) {
+ int rawSz = dataSz; /* keep raw size for hmac */
+
+ ssl->hmac(ssl, verify, rawData, rawSz, application_data, 1);
+
+#ifdef HAVE_LIBZ
+ byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+
+ if (ssl->options.usingCompression) {
+ dataSz = DeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp));
+ if (dataSz < 0) return dataSz;
+ }
+#endif
+
+ if (ssl->options.usingCompression)
+ idx += rawSz;
+ else
+ idx += dataSz;
+
+ ssl->buffers.clearOutputBuffer.buffer = rawData;
+ ssl->buffers.clearOutputBuffer.length = dataSz;
+ }
+
+ /* read mac and fill */
+ mac = input + idx;
+ idx += digestSz;
+
+ idx += pad;
+ if (padByte)
+ idx++;
+
+#ifdef HAVE_LIBZ
+ if (ssl->options.usingCompression)
+ XMEMMOVE(rawData, decomp, dataSz);
+#endif
+
+ /* verify */
+ if (dataSz) {
+ if (XMEMCMP(mac, verify, digestSz))
+ return VERIFY_MAC_ERROR;
+ }
+ else
+ GetSEQIncrement(ssl, 1); /* even though no data, increment verify */
+
+ *inOutIdx = idx;
+ return 0;
+}
+
+
+/* process alert, return level */
+static int DoAlert(SSL* ssl, byte* input, word32* inOutIdx, int* type)
+{
+ byte level;
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("Alert", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ /* add record header back on to info + 2 byte level, data */
+ AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx -
+ RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap);
+ #endif
+ level = input[(*inOutIdx)++];
+ *type = (int)input[(*inOutIdx)++];
+
+ if (*type == close_notify)
+ ssl->options.closeNotify = 1;
+
+ if (ssl->keys.encryptionOn) {
+ int aSz = ALERT_SIZE;
+ const byte* mac;
+ byte verify[SHA_DIGEST_SIZE];
+ int padSz = ssl->keys.encryptSz - aSz - ssl->specs.hash_size;
+
+ ssl->hmac(ssl, verify, input + *inOutIdx - aSz, aSz, alert, 1);
+
+ /* read mac and fill */
+ mac = input + *inOutIdx;
+ *inOutIdx += (ssl->specs.hash_size + padSz);
+
+ /* verify */
+ if (XMEMCMP(mac, verify, ssl->specs.hash_size))
+ return VERIFY_MAC_ERROR;
+ }
+
+ return level;
+}
+
+static int GetInputData(SSL *ssl, size_t size)
+{
+ int in;
+ int inSz;
+ int maxLength;
+ int usedLength;
+
+
+ /* check max input length */
+ usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx;
+ maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength;
+ inSz = (int)(size - usedLength); /* from last partial read */
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ inSz = 1500; /* read ahead up to MTU */
+#endif
+
+ if (inSz > maxLength) {
+ if (GrowInputBuffer(ssl, size, usedLength) < 0)
+ return MEMORY_E;
+ }
+
+ if (inSz <= 0)
+ return BUFFER_ERROR;
+
+ /* Put buffer data at start if not there */
+ if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0)
+ XMEMMOVE(ssl->buffers.inputBuffer.buffer,
+ ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
+ usedLength);
+
+ /* remove processed data */
+ ssl->buffers.inputBuffer.idx = 0;
+ ssl->buffers.inputBuffer.length = usedLength;
+
+ /* read data from network */
+ do {
+ in = Receive(ssl,
+ ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.length,
+ inSz, 0);
+ if (in == -1)
+ return SOCKET_ERROR_E;
+
+ if (in == WANT_READ)
+ return WANT_READ;
+
+ ssl->buffers.inputBuffer.length += in;
+ inSz -= in;
+
+ } while (ssl->buffers.inputBuffer.length < size);
+
+ return 0;
+}
+
+/* process input requests, return 0 is done, 1 is call again to complete, and
+ negative number is error */
+int ProcessReply(SSL* ssl)
+{
+ int ret, type, readSz;
+ word32 startIdx = 0;
+ byte b0, b1;
+#ifdef CYASSL_DTLS
+ int used;
+#endif
+
+ for (;;) {
+ switch ((processReply)ssl->options.processReply) {
+
+ /* in the CYASSL_SERVER case, get the first byte for detecting
+ * old client hello */
+ case doProcessInit:
+
+ readSz = RECORD_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ readSz = DTLS_RECORD_HEADER_SZ;
+ #endif
+
+ /* get header or return error */
+ if (!ssl->options.dtls) {
+ if ((ret = GetInputData(ssl, readSz)) < 0)
+ return ret;
+ } else {
+ #ifdef CYASSL_DTLS
+ /* read ahead may already have header */
+ used = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (used < readSz)
+ if ((ret = GetInputData(ssl, readSz)) < 0)
+ return ret;
+ #endif
+ }
+
+#ifndef NO_CYASSL_SERVER
+
+ /* see if sending SSLv2 client hello */
+ if ( ssl->options.side == SERVER_END &&
+ ssl->options.clientState == NULL_STATE &&
+ ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx]
+ != handshake) {
+ ssl->options.processReply = runProcessOldClientHello;
+
+ /* how many bytes need ProcessOldClientHello */
+ b0 =
+ ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+ b1 =
+ ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++];
+ ssl->curSize = ((b0 & 0x7f) << 8) | b1;
+ }
+ else {
+ ssl->options.processReply = getRecordLayerHeader;
+ continue;
+ }
+
+ /* in the CYASSL_SERVER case, run the old client hello */
+ case runProcessOldClientHello:
+
+ /* get sz bytes or return error */
+ if (!ssl->options.dtls) {
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+ } else {
+ #ifdef CYASSL_DTLS
+ /* read ahead may already have */
+ used = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (used < ssl->curSize)
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+ #endif /* CYASSL_DTLS */
+ }
+
+ ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx,
+ ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx,
+ ssl->curSize);
+ if (ret < 0)
+ return ret;
+
+ else if (ssl->buffers.inputBuffer.idx ==
+ ssl->buffers.inputBuffer.length) {
+ ssl->options.processReply = doProcessInit;
+ return 0;
+ }
+
+#endif /* NO_CYASSL_SERVER */
+
+ /* get the record layer header */
+ case getRecordLayerHeader:
+
+ ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx,
+ &ssl->curRL, &ssl->curSize);
+ if (ret != 0)
+ return ret;
+
+ ssl->options.processReply = getData;
+
+ /* retrieve record layer data */
+ case getData:
+
+ /* get sz bytes or return error */
+ if (!ssl->options.dtls) {
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+ } else {
+#ifdef CYASSL_DTLS
+ /* read ahead may already have */
+ used = ssl->buffers.inputBuffer.length -
+ ssl->buffers.inputBuffer.idx;
+ if (used < ssl->curSize)
+ if ((ret = GetInputData(ssl, ssl->curSize)) < 0)
+ return ret;
+#endif
+ }
+
+ ssl->options.processReply = runProcessingOneMessage;
+ startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
+
+ /* the record layer is here */
+ case runProcessingOneMessage:
+
+ if (ssl->keys.encryptionOn)
+ if (DecryptMessage(ssl, ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.idx,
+ ssl->curSize,
+ &ssl->buffers.inputBuffer.idx) < 0)
+ return DECRYPT_ERROR;
+
+ CYASSL_MSG("received record layer msg");
+
+ switch (ssl->curRL.type) {
+ case handshake :
+ /* debugging in DoHandShakeMsg */
+ if ((ret = DoHandShakeMsg(ssl,
+ ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx,
+ ssl->buffers.inputBuffer.length))
+ != 0)
+ return ret;
+ break;
+
+ case change_cipher_spec:
+ CYASSL_MSG("got CHANGE CIPHER SPEC");
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ChangeCipher", &ssl->handShakeInfo);
+ /* add record header back on info */
+ if (ssl->toInfoOn) {
+ AddPacketInfo("ChangeCipher", &ssl->timeoutInfo,
+ ssl->buffers.inputBuffer.buffer +
+ ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ,
+ 1 + RECORD_HEADER_SZ, ssl->heap);
+ AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo);
+ }
+ #endif
+ ssl->buffers.inputBuffer.idx++;
+ ssl->keys.encryptionOn = 1;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ ssl->keys.dtls_peer_epoch++;
+ #endif
+
+ #ifdef HAVE_LIBZ
+ if (ssl->options.usingCompression)
+ if ( (ret = InitStreams(ssl)) != 0)
+ return ret;
+ #endif
+ if (ssl->options.resuming && ssl->options.side ==
+ CLIENT_END)
+ BuildFinished(ssl, &ssl->verifyHashes, server);
+ else if (!ssl->options.resuming && ssl->options.side ==
+ SERVER_END)
+ BuildFinished(ssl, &ssl->verifyHashes, client);
+ break;
+
+ case application_data:
+ CYASSL_MSG("got app DATA");
+ if ((ret = DoApplicationData(ssl,
+ ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx))
+ != 0) {
+ CYASSL_ERROR(ret);
+ return ret;
+ }
+ break;
+
+ case alert:
+ CYASSL_MSG("got ALERT!");
+ if (DoAlert(ssl, ssl->buffers.inputBuffer.buffer,
+ &ssl->buffers.inputBuffer.idx, &type) == alert_fatal)
+ return FATAL_ERROR;
+
+ /* catch warnings that are handled as errors */
+ if (type == close_notify)
+ return ssl->error = ZERO_RETURN;
+
+ if (type == decrypt_error)
+ return FATAL_ERROR;
+ break;
+
+ default:
+ CYASSL_ERROR(UNKNOWN_RECORD_TYPE);
+ return UNKNOWN_RECORD_TYPE;
+ }
+
+ ssl->options.processReply = doProcessInit;
+
+ /* input exhausted? */
+ if (ssl->buffers.inputBuffer.idx == ssl->buffers.inputBuffer.length)
+ return 0;
+ /* more messages per record */
+ else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
+ #ifdef CYASSL_DTLS
+ /* read-ahead but dtls doesn't bundle messages per record */
+ if (ssl->options.dtls) {
+ ssl->options.processReply = doProcessInit;
+ continue;
+ }
+ #endif
+ ssl->options.processReply = runProcessingOneMessage;
+ continue;
+ }
+ /* more records */
+ else {
+ ssl->options.processReply = doProcessInit;
+ continue;
+ }
+ }
+ }
+}
+
+
+int SendChangeCipher(SSL* ssl)
+{
+ byte *output;
+ int sendSz = RECORD_HEADER_SZ + ENUM_LEN;
+ int idx = RECORD_HEADER_SZ;
+ int ret;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA;
+ idx += DTLS_RECORD_EXTRA;
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddRecordHeader(output, 1, change_cipher_spec, ssl);
+
+ output[idx] = 1; /* turn it on */
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ChangeCipher", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ChangeCipher", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+}
+
+
+static INLINE const byte* GetMacSecret(SSL* ssl, int verify)
+{
+ if ( (ssl->options.side == CLIENT_END && !verify) ||
+ (ssl->options.side == SERVER_END && verify) )
+ return ssl->keys.client_write_MAC_secret;
+ else
+ return ssl->keys.server_write_MAC_secret;
+}
+
+
+static void Hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify)
+{
+ byte result[SHA_DIGEST_SIZE]; /* max possible sizes */
+ word32 digestSz = ssl->specs.hash_size; /* actual sizes */
+ word32 padSz = ssl->specs.pad_size;
+
+ Md5 md5;
+ Sha sha;
+
+ /* data */
+ byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */
+ const byte* macSecret = GetMacSecret(ssl, verify);
+
+ conLen[0] = content;
+ c16toa((word16)sz, &conLen[ENUM_LEN]);
+ c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
+
+ if (ssl->specs.mac_algorithm == md5_mac) {
+ InitMd5(&md5);
+ /* inner */
+ Md5Update(&md5, macSecret, digestSz);
+ Md5Update(&md5, PAD1, padSz);
+ Md5Update(&md5, seq, SEQ_SZ);
+ Md5Update(&md5, conLen, sizeof(conLen));
+ /* buffer */
+ Md5Update(&md5, buffer, sz);
+ Md5Final(&md5, result);
+ /* outer */
+ Md5Update(&md5, macSecret, digestSz);
+ Md5Update(&md5, PAD2, padSz);
+ Md5Update(&md5, result, digestSz);
+ Md5Final(&md5, digest);
+ }
+ else {
+ InitSha(&sha);
+ /* inner */
+ ShaUpdate(&sha, macSecret, digestSz);
+ ShaUpdate(&sha, PAD1, padSz);
+ ShaUpdate(&sha, seq, SEQ_SZ);
+ ShaUpdate(&sha, conLen, sizeof(conLen));
+ /* buffer */
+ ShaUpdate(&sha, buffer, sz);
+ ShaFinal(&sha, result);
+ /* outer */
+ ShaUpdate(&sha, macSecret, digestSz);
+ ShaUpdate(&sha, PAD2, padSz);
+ ShaUpdate(&sha, result, digestSz);
+ ShaFinal(&sha, digest);
+ }
+}
+
+
+static void BuildMD5_CertVerify(SSL* ssl, byte* digest)
+{
+ byte md5_result[MD5_DIGEST_SIZE];
+
+ /* make md5 inner */
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD1, PAD_MD5);
+ Md5Final(&ssl->hashMd5, md5_result);
+
+ /* make md5 outer */
+ Md5Update(&ssl->hashMd5, ssl->arrays.masterSecret, SECRET_LEN);
+ Md5Update(&ssl->hashMd5, PAD2, PAD_MD5);
+ Md5Update(&ssl->hashMd5, md5_result, MD5_DIGEST_SIZE);
+
+ Md5Final(&ssl->hashMd5, digest);
+}
+
+
+static void BuildSHA_CertVerify(SSL* ssl, byte* digest)
+{
+ byte sha_result[SHA_DIGEST_SIZE];
+
+ /* make sha inner */
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD1, PAD_SHA);
+ ShaFinal(&ssl->hashSha, sha_result);
+
+ /* make sha outer */
+ ShaUpdate(&ssl->hashSha, ssl->arrays.masterSecret, SECRET_LEN);
+ ShaUpdate(&ssl->hashSha, PAD2, PAD_SHA);
+ ShaUpdate(&ssl->hashSha, sha_result, SHA_DIGEST_SIZE);
+
+ ShaFinal(&ssl->hashSha, digest);
+}
+
+
+static void BuildCertHashes(SSL* ssl, Hashes* hashes)
+{
+ /* store current states, building requires get_digest which resets state */
+ Md5 md5 = ssl->hashMd5;
+ Sha sha = ssl->hashSha;
+
+ if (ssl->options.tls) {
+ Md5Final(&ssl->hashMd5, hashes->md5);
+ ShaFinal(&ssl->hashSha, hashes->sha);
+ }
+ else {
+ BuildMD5_CertVerify(ssl, hashes->md5);
+ BuildSHA_CertVerify(ssl, hashes->sha);
+ }
+
+ /* restore */
+ ssl->hashMd5 = md5;
+ ssl->hashSha = sha;
+}
+
+
+/* Build SSL Message, encrypted */
+static int BuildMessage(SSL* ssl, byte* output, const byte* input, int inSz,
+ int type)
+{
+ word32 digestSz = ssl->specs.hash_size;
+ word32 sz = RECORD_HEADER_SZ + inSz + digestSz;
+ word32 pad = 0, i;
+ word32 idx = RECORD_HEADER_SZ;
+ word32 ivSz = 0; /* TLSv1.1 IV */
+ word32 headerSz = RECORD_HEADER_SZ;
+ word16 size;
+ byte iv[AES_BLOCK_SIZE]; /* max size */
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sz += DTLS_RECORD_EXTRA;
+ idx += DTLS_RECORD_EXTRA;
+ headerSz += DTLS_RECORD_EXTRA;
+ }
+#endif
+
+ if (ssl->specs.cipher_type == block) {
+ word32 blockSz = ssl->specs.block_size;
+ if (ssl->options.tls1_1) {
+ ivSz = blockSz;
+ sz += ivSz;
+ RNG_GenerateBlock(&ssl->rng, iv, ivSz);
+ }
+ sz += 1; /* pad byte */
+ pad = (sz - headerSz) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ size = sz - headerSz; /* include mac and digest */
+ AddRecordHeader(output, size, type, ssl);
+
+ /* write to output */
+ if (ivSz) {
+ XMEMCPY(output + idx, iv, ivSz);
+ idx += ivSz;
+ }
+ XMEMCPY(output + idx, input, inSz);
+ idx += inSz;
+
+ if (type == handshake)
+ HashOutput(ssl, output, headerSz + inSz, ivSz);
+ ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, type, 0);
+ idx += digestSz;
+
+ if (ssl->specs.cipher_type == block)
+ for (i = 0; i <= pad; i++) output[idx++] = pad; /* pad byte gets */
+ /* pad value too */
+ Encrypt(ssl, output + headerSz, output + headerSz, size);
+
+ return sz;
+}
+
+
+int SendFinished(SSL* ssl)
+{
+ int sendSz,
+ finishedSz = ssl->options.tls ? TLS_FINISHED_SZ :
+ FINISHED_SZ;
+ byte input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ]; /* max */
+ byte *output;
+ Hashes* hashes;
+ int ret;
+ int headerSz = HANDSHAKE_HEADER_SZ;
+
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ headerSz += DTLS_HANDSHAKE_EXTRA;
+ ssl->keys.dtls_epoch++;
+ ssl->keys.dtls_sequence_number = 0; /* reset after epoch change */
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sizeof(input) + MAX_MSG_EXTRA)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHandShakeHeader(input, finishedSz, finished, ssl);
+
+ /* make finished hashes */
+ hashes = (Hashes*)&input[headerSz];
+ BuildFinished(ssl, hashes, ssl->options.side == CLIENT_END ? client :
+ server);
+
+ if ( (sendSz = BuildMessage(ssl, output, input, headerSz +
+ finishedSz, handshake)) == -1)
+ return BUILD_MSG_ERROR;
+
+ if (!ssl->options.resuming) {
+ AddSession(ssl); /* just try */
+ if (ssl->options.side == CLIENT_END)
+ BuildFinished(ssl, &ssl->verifyHashes, server);
+ else
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ }
+ else {
+ if (ssl->options.side == CLIENT_END)
+ ssl->options.handShakeState = HANDSHAKE_DONE;
+ else
+ BuildFinished(ssl, &ssl->verifyHashes, client);
+ }
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+}
+
+
+int SendCertificate(SSL* ssl)
+{
+ int sendSz, length, ret = 0;
+ word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ word32 certSz, listSz;
+ byte* output = 0;
+
+ if (ssl->options.usingPSK_cipher) return 0; /* not needed */
+
+ if (ssl->options.sendVerify == SEND_BLANK_CERT) {
+ certSz = 0;
+ length = CERT_HEADER_SZ;
+ listSz = 0;
+ }
+ else {
+ certSz = ssl->buffers.certificate.length;
+ /* list + cert size */
+ length = certSz + 2 * CERT_HEADER_SZ;
+ listSz = certSz + CERT_HEADER_SZ;
+ }
+ sendSz = length + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, certificate, ssl);
+
+ /* list total */
+ c32to24(listSz, output + i);
+ i += CERT_HEADER_SZ;
+
+ /* member */
+ if (certSz) {
+ c32to24(certSz, output + i);
+ i += CERT_HEADER_SZ;
+ XMEMCPY(output + i, ssl->buffers.certificate.buffer, certSz);
+ i += certSz;
+ }
+ HashOutput(ssl, output, sendSz, 0);
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+
+ if (ssl->options.side == SERVER_END)
+ ssl->options.serverState = SERVER_CERT_COMPLETE;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+}
+
+
+int SendCertificateRequest(SSL* ssl)
+{
+ byte *output;
+ int ret;
+ int sendSz;
+ word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+
+ int typeTotal = 1; /* only rsa for now */
+ int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */
+
+ if (ssl->options.usingPSK_cipher) return 0; /* not needed */
+
+ sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, reqSz, certificate_request, ssl);
+
+ /* write to output */
+ output[i++] = typeTotal; /* # of types */
+ output[i++] = rsa_sign;
+
+ c16toa(0, &output[i]); /* auth's */
+ i += REQ_HEADER_SZ;
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateRequest", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output,
+ sendSz, ssl->heap);
+ #endif
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+}
+
+
+int SendData(SSL* ssl, const void* buffer, int sz)
+{
+ int sent = 0, /* plainText size */
+ sendSz,
+ ret;
+
+ if (ssl->error == WANT_WRITE)
+ ssl->error = 0;
+
+ if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+ int err;
+ if ( (err = CyaSSL_negotiate(ssl)) != 0)
+ return err;
+ }
+
+ /* last time system socket output buffer was full, try again to send */
+ if (ssl->buffers.outputBuffer.length > 0) {
+ if ( (ssl->error = SendBuffered(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ if (ssl->error == SOCKET_ERROR_E && ssl->options.connReset)
+ return 0; /* peer reset */
+ return ssl->error;
+ }
+ else {
+ /* advance sent to previous sent + plain size just sent */
+ sent = ssl->buffers.prevSent + ssl->buffers.plainSz;
+ CYASSL_MSG("sent write buffered data");
+ }
+ }
+
+ for (;;) {
+ int len = min(sz - sent, OUTPUT_RECORD_SIZE);
+ byte* out;
+ byte* sendBuffer = (byte*)buffer + sent; /* may switch on comp */
+ int buffSz = len; /* may switch on comp */
+#ifdef HAVE_LIBZ
+ byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA];
+#endif
+
+ if (sent == sz) break;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ len = min(len, MAX_UDP_SIZE);
+ buffSz = len;
+ }
+#endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, len + COMP_EXTRA +
+ MAX_MSG_EXTRA)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ out = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+#ifdef HAVE_LIBZ
+ if (ssl->options.usingCompression) {
+ buffSz = Compress(ssl, sendBuffer, buffSz, comp, sizeof(comp));
+ if (buffSz < 0) {
+ return buffSz;
+ }
+ sendBuffer = comp;
+ }
+#endif
+ sendSz = BuildMessage(ssl, out, sendBuffer, buffSz,
+ application_data);
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ if ( (ret = SendBuffered(ssl)) < 0) {
+ CYASSL_ERROR(ret);
+ /* store for next call if WANT_WRITE or user embedSend() that
+ doesn't present like WANT_WRITE */
+ ssl->buffers.plainSz = len;
+ ssl->buffers.prevSent = sent;
+ if (ret == SOCKET_ERROR_E && ssl->options.connReset)
+ return 0; /* peer reset */
+ return ssl->error = ret;
+ }
+
+ sent += len;
+
+ /* only one message per attempt */
+ if (ssl->options.partialWrite == 1)
+ break;
+ }
+
+ return sent;
+}
+
+/* process input data */
+int ReceiveData(SSL* ssl, byte* output, int sz)
+{
+ int size;
+
+ CYASSL_ENTER("ReceiveData()");
+
+ if (ssl->error == WANT_READ)
+ ssl->error = 0;
+
+ if (ssl->options.handShakeState != HANDSHAKE_DONE) {
+ int err;
+ if ( (err = CyaSSL_negotiate(ssl)) != 0)
+ return err;
+ }
+
+ while (ssl->buffers.clearOutputBuffer.length == 0)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ if (ssl->error == ZERO_RETURN) {
+ ssl->options.isClosed = 1;
+ return 0; /* no more data coming */
+ }
+ if (ssl->error == SOCKET_ERROR_E)
+ if (ssl->options.connReset || ssl->options.isClosed)
+ return 0; /* peer reset or closed */
+ return ssl->error;
+ }
+
+ if (sz < (int)ssl->buffers.clearOutputBuffer.length)
+ size = sz;
+ else
+ size = ssl->buffers.clearOutputBuffer.length;
+
+ XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size);
+ ssl->buffers.clearOutputBuffer.length -= size;
+ ssl->buffers.clearOutputBuffer.buffer += size;
+
+ if (ssl->buffers.clearOutputBuffer.length == 0 &&
+ ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+
+ CYASSL_LEAVE("ReceiveData()", size);
+ return size;
+}
+
+
+/* send alert message */
+int SendAlert(SSL* ssl, int severity, int type)
+{
+ byte input[ALERT_SIZE];
+ byte *output;
+ int sendSz;
+ int ret;
+
+ /* if sendalert is called again for nonbloking */
+ if (ssl->options.sendAlertState != 0) {
+ ret = SendBuffered(ssl);
+ if (ret == 0)
+ ssl->options.sendAlertState = 0;
+ return ret;
+ }
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, ALERT_SIZE + MAX_MSG_EXTRA)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ input[0] = severity;
+ input[1] = type;
+
+ if (ssl->keys.encryptionOn)
+ sendSz = BuildMessage(ssl, output, input, sizeof(input), alert);
+ else {
+ RecordLayerHeader *const rl = (RecordLayerHeader*)output;
+ rl->type = alert;
+ rl->version = ssl->version;
+ c16toa(ALERT_SIZE, rl->length);
+
+ XMEMCPY(output + RECORD_HEADER_SZ, input, sizeof(input));
+ sendSz = RECORD_HEADER_SZ + sizeof(input);
+ }
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("Alert", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("Alert", &ssl->timeoutInfo, output, sendSz,ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ ssl->options.sendAlertState = 1;
+
+ return SendBuffered(ssl);
+}
+
+
+
+void SetErrorString(int error, char* buffer)
+{
+ const int max = MAX_ERROR_SZ; /* shorthand */
+
+#ifdef NO_ERROR_STRINGS
+
+ XSTRNCPY(buffer, "no support for error strings built in", max);
+
+#else
+
+ /* pass to CTaoCrypt */
+ if (error < MAX_CODE_E && error > MIN_CODE_E) {
+ CTaoCryptErrorString(error, buffer);
+ return;
+ }
+
+ switch (error) {
+
+ case UNSUPPORTED_SUITE :
+ XSTRNCPY(buffer, "unsupported cipher suite", max);
+ break;
+
+ case PREFIX_ERROR :
+ XSTRNCPY(buffer, "bad index to key rounds", max);
+ break;
+
+ case MEMORY_ERROR :
+ XSTRNCPY(buffer, "out of memory", max);
+ break;
+
+ case VERIFY_FINISHED_ERROR :
+ XSTRNCPY(buffer, "verify problem on finished", max);
+ break;
+
+ case VERIFY_MAC_ERROR :
+ XSTRNCPY(buffer, "verify mac problem", max);
+ break;
+
+ case PARSE_ERROR :
+ XSTRNCPY(buffer, "parse error on header", max);
+ break;
+
+ case SIDE_ERROR :
+ XSTRNCPY(buffer, "wrong client/server type", max);
+ break;
+
+ case NO_PEER_CERT :
+ XSTRNCPY(buffer, "peer didn't send cert", max);
+ break;
+
+ case UNKNOWN_HANDSHAKE_TYPE :
+ XSTRNCPY(buffer, "weird handshake type", max);
+ break;
+
+ case SOCKET_ERROR_E :
+ XSTRNCPY(buffer, "error state on socket", max);
+ break;
+
+ case SOCKET_NODATA :
+ XSTRNCPY(buffer, "expected data, not there", max);
+ break;
+
+ case INCOMPLETE_DATA :
+ XSTRNCPY(buffer, "don't have enough data to complete task", max);
+ break;
+
+ case UNKNOWN_RECORD_TYPE :
+ XSTRNCPY(buffer, "unknown type in record hdr", max);
+ break;
+
+ case DECRYPT_ERROR :
+ XSTRNCPY(buffer, "error during decryption", max);
+ break;
+
+ case FATAL_ERROR :
+ XSTRNCPY(buffer, "revcd alert fatal error", max);
+ break;
+
+ case ENCRYPT_ERROR :
+ XSTRNCPY(buffer, "error during encryption", max);
+ break;
+
+ case FREAD_ERROR :
+ XSTRNCPY(buffer, "fread problem", max);
+ break;
+
+ case NO_PEER_KEY :
+ XSTRNCPY(buffer, "need peer's key", max);
+ break;
+
+ case NO_PRIVATE_KEY :
+ XSTRNCPY(buffer, "need the private key", max);
+ break;
+
+ case RSA_PRIVATE_ERROR :
+ XSTRNCPY(buffer, "error during rsa priv op", max);
+ break;
+
+ case MATCH_SUITE_ERROR :
+ XSTRNCPY(buffer, "can't match cipher suite", max);
+ break;
+
+ case BUILD_MSG_ERROR :
+ XSTRNCPY(buffer, "build message failure", max);
+ break;
+
+ case BAD_HELLO :
+ XSTRNCPY(buffer, "client hello malformed", max);
+ break;
+
+ case DOMAIN_NAME_MISMATCH :
+ XSTRNCPY(buffer, "peer subject name mismatch", max);
+ break;
+
+ case WANT_READ :
+ XSTRNCPY(buffer, "non-blocking socket wants data to be read", max);
+ break;
+
+ case NOT_READY_ERROR :
+ XSTRNCPY(buffer, "handshake layer not ready yet, complete first", max);
+ break;
+
+ case PMS_VERSION_ERROR :
+ XSTRNCPY(buffer, "premaster secret version mismatch error", max);
+ break;
+
+ case VERSION_ERROR :
+ XSTRNCPY(buffer, "record layer version error", max);
+ break;
+
+ case WANT_WRITE :
+ XSTRNCPY(buffer, "non-blocking socket write buffer full", max);
+ break;
+
+ case BUFFER_ERROR :
+ XSTRNCPY(buffer, "malformed buffer input error", max);
+ break;
+
+ case VERIFY_CERT_ERROR :
+ XSTRNCPY(buffer, "verify problem on certificate", max);
+ break;
+
+ case VERIFY_SIGN_ERROR :
+ XSTRNCPY(buffer, "verify problem based on signature", max);
+ break;
+
+ case CLIENT_ID_ERROR :
+ XSTRNCPY(buffer, "psk client identity error", max);
+ break;
+
+ case SERVER_HINT_ERROR:
+ XSTRNCPY(buffer, "psk server hint error", max);
+ break;
+
+ case PSK_KEY_ERROR:
+ XSTRNCPY(buffer, "psk key callback error", max);
+ break;
+
+ case NTRU_KEY_ERROR:
+ XSTRNCPY(buffer, "NTRU key error", max);
+ break;
+
+ case NTRU_DRBG_ERROR:
+ XSTRNCPY(buffer, "NTRU drbg error", max);
+ break;
+
+ case NTRU_ENCRYPT_ERROR:
+ XSTRNCPY(buffer, "NTRU encrypt error", max);
+ break;
+
+ case NTRU_DECRYPT_ERROR:
+ XSTRNCPY(buffer, "NTRU decrypt error", max);
+ break;
+
+ case ZLIB_INIT_ERROR:
+ XSTRNCPY(buffer, "zlib init error", max);
+ break;
+
+ case ZLIB_COMPRESS_ERROR:
+ XSTRNCPY(buffer, "zlib compress error", max);
+ break;
+
+ case ZLIB_DECOMPRESS_ERROR:
+ XSTRNCPY(buffer, "zlib decompress error", max);
+ break;
+
+ case GETTIME_ERROR:
+ XSTRNCPY(buffer, "gettimeofday() error", max);
+ break;
+
+ case GETITIMER_ERROR:
+ XSTRNCPY(buffer, "getitimer() error", max);
+ break;
+
+ case SIGACT_ERROR:
+ XSTRNCPY(buffer, "sigaction() error", max);
+ break;
+
+ case SETITIMER_ERROR:
+ XSTRNCPY(buffer, "setitimer() error", max);
+ break;
+
+ case LENGTH_ERROR:
+ XSTRNCPY(buffer, "record layer length error", max);
+ break;
+
+ case PEER_KEY_ERROR:
+ XSTRNCPY(buffer, "cant decode peer key", max);
+ break;
+
+ case ZERO_RETURN:
+ XSTRNCPY(buffer, "peer sent close notify alert", max);
+ break;
+
+ default :
+ XSTRNCPY(buffer, "unknown error number", max);
+ }
+
+#endif /* NO_ERROR_STRINGS */
+}
+
+
+
+/* be sure to add to cipher_name_idx too !!!! */
+const char* const cipher_names[] =
+{
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ "RC4-SHA",
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ "RC4-MD5",
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ "DES-CBC3-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ "AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ "AES256-SHA",
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ "DHE-RSA-AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ "DHE-RSA-AES256-SHA",
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ "PSK-AES128-CBC-SHA",
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ "PSK-AES256-CBC-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ "HC128-MD5",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ "HC128-SHA",
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ "RABBIT-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ "NTRU-RC4-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ "NTRU-DES-CBC3-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ "NTRU-AES128-SHA",
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ "NTRU-AES256-SHA",
+#endif
+};
+
+
+
+/* cipher suite number that matches above name table */
+int cipher_name_idx[] =
+{
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ SSL_RSA_WITH_RC4_128_SHA,
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ SSL_RSA_WITH_RC4_128_MD5,
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ TLS_RSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ TLS_RSA_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ TLS_PSK_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ TLS_PSK_WITH_AES_256_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ TLS_RSA_WITH_HC_128_CBC_MD5,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ TLS_RSA_WITH_HC_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ TLS_RSA_WITH_RABBIT_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ TLS_NTRU_RSA_WITH_RC4_128_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ TLS_NTRU_RSA_WITH_AES_128_CBC_SHA,
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ TLS_NTRU_RSA_WITH_AES_256_CBC_SHA,
+#endif
+};
+
+
+/* return true if set, else false */
+/* only supports full name from cipher_name[] delimited by : */
+int SetCipherList(SSL_CTX* ctx, const char* list)
+{
+ int ret = 0, i;
+ char name[MAX_SUITE_NAME];
+
+ char needle[] = ":";
+ char* haystack = (char*)list;
+ char* prev;
+
+ const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]);
+ int idx = 0;
+
+ if (!list)
+ return 0;
+
+ if (*list == 0) return 1; /* CyaSSL default */
+
+ if (XSTRNCMP(haystack, "ALL", 3) == 0) return 1; /* CyaSSL defualt */
+
+ for(;;) {
+ size_t len;
+ prev = haystack;
+ haystack = XSTRSTR(haystack, needle);
+
+ if (!haystack) /* last cipher */
+ len = min(sizeof(name), XSTRLEN(prev));
+ else
+ len = min(sizeof(name), (size_t)(haystack - prev));
+
+ XSTRNCPY(name, prev, len);
+ name[(len == sizeof(name)) ? len - 1 : len] = 0;
+
+ for (i = 0; i < suiteSz; i++)
+ if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
+
+ ctx->suites.suites[idx++] = 0x00; /* first byte always zero */
+ ctx->suites.suites[idx++] = cipher_name_idx[i];
+
+ if (!ret) ret = 1; /* found at least one */
+ break;
+ }
+ if (!haystack) break;
+ haystack++;
+ }
+
+ if (ret) {
+ ctx->suites.setSuites = 1;
+ ctx->suites.suiteSz = idx;
+ }
+
+ return ret;
+}
+
+
+#ifdef CYASSL_CALLBACKS
+
+ /* Initialisze HandShakeInfo */
+ void InitHandShakeInfo(HandShakeInfo* info)
+ {
+ int i;
+
+ info->cipherName[0] = 0;
+ for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+ info->packetNames[i][0] = 0;
+ info->numberPackets = 0;
+ info->negotiationError = 0;
+ }
+
+ /* Set Final HandShakeInfo parameters */
+ void FinishHandShakeInfo(HandShakeInfo* info, const SSL* ssl)
+ {
+ int i;
+ int sz = sizeof(cipher_name_idx)/sizeof(int);
+
+ for (i = 0; i < sz; i++)
+ if (ssl->options.cipherSuite == (byte)cipher_name_idx[i]) {
+ XSTRNCPY(info->cipherName, cipher_names[i], MAX_CIPHERNAME_SZ);
+ break;
+ }
+
+ /* error max and min are negative numbers */
+ if (ssl->error <= MIN_PARAM_ERR && ssl->error >= MAX_PARAM_ERR)
+ info->negotiationError = ssl->error;
+ }
+
+
+ /* Add name to info packet names, increase packet name count */
+ void AddPacketName(const char* name, HandShakeInfo* info)
+ {
+ if (info->numberPackets < MAX_PACKETS_HANDSHAKE) {
+ XSTRNCPY(info->packetNames[info->numberPackets++], name,
+ MAX_PACKETNAME_SZ);
+ }
+ }
+
+
+ /* Initialisze TimeoutInfo */
+ void InitTimeoutInfo(TimeoutInfo* info)
+ {
+ int i;
+
+ info->timeoutName[0] = 0;
+ info->flags = 0;
+
+ for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) {
+ info->packets[i].packetName[0] = 0;
+ info->packets[i].timestamp.tv_sec = 0;
+ info->packets[i].timestamp.tv_usec = 0;
+ info->packets[i].bufferValue = 0;
+ info->packets[i].valueSz = 0;
+ }
+ info->numberPackets = 0;
+ info->timeoutValue.tv_sec = 0;
+ info->timeoutValue.tv_usec = 0;
+ }
+
+
+ /* Free TimeoutInfo */
+ void FreeTimeoutInfo(TimeoutInfo* info, void* heap)
+ {
+ int i;
+ for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++)
+ if (info->packets[i].bufferValue) {
+ XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO);
+ info->packets[i].bufferValue = 0;
+ }
+
+ }
+
+
+ /* Add PacketInfo to TimeoutInfo */
+ void AddPacketInfo(const char* name, TimeoutInfo* info, const byte* data,
+ int sz, void* heap)
+ {
+ if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) {
+ Timeval currTime;
+
+ /* may add name after */
+ if (name)
+ XSTRNCPY(info->packets[info->numberPackets].packetName, name,
+ MAX_PACKETNAME_SZ);
+
+ /* add data, put in buffer if bigger than static buffer */
+ info->packets[info->numberPackets].valueSz = sz;
+ if (sz < MAX_VALUE_SZ)
+ XMEMCPY(info->packets[info->numberPackets].value, data, sz);
+ else {
+ info->packets[info->numberPackets].bufferValue =
+ XMALLOC(sz, heap, DYNAMIC_TYPE_INFO);
+ if (!info->packets[info->numberPackets].bufferValue)
+ /* let next alloc catch, just don't fill, not fatal here */
+ info->packets[info->numberPackets].valueSz = 0;
+ else
+ XMEMCPY(info->packets[info->numberPackets].bufferValue,
+ data, sz);
+ }
+ gettimeofday(&currTime, 0);
+ info->packets[info->numberPackets].timestamp.tv_sec =
+ currTime.tv_sec;
+ info->packets[info->numberPackets].timestamp.tv_usec =
+ currTime.tv_usec;
+ info->numberPackets++;
+ }
+ }
+
+
+ /* Add packet name to previsouly added packet info */
+ void AddLateName(const char* name, TimeoutInfo* info)
+ {
+ /* make sure we have a valid previous one */
+ if (info->numberPackets > 0 && info->numberPackets <
+ MAX_PACKETS_HANDSHAKE) {
+ XSTRNCPY(info->packets[info->numberPackets - 1].packetName, name,
+ MAX_PACKETNAME_SZ);
+ }
+ }
+
+ /* Add record header to previsouly added packet info */
+ void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info)
+ {
+ /* make sure we have a valid previous one */
+ if (info->numberPackets > 0 && info->numberPackets <
+ MAX_PACKETS_HANDSHAKE) {
+ if (info->packets[info->numberPackets - 1].bufferValue)
+ XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl,
+ RECORD_HEADER_SZ);
+ else
+ XMEMCPY(info->packets[info->numberPackets - 1].value, rl,
+ RECORD_HEADER_SZ);
+ }
+ }
+
+#endif /* CYASSL_CALLBACKS */
+
+
+
+/* client only parts */
+#ifndef NO_CYASSL_CLIENT
+
+ int SendClientHello(SSL* ssl)
+ {
+ byte *output;
+ word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ int idSz = ssl->options.resuming ? ID_LEN : 0;
+ int ret;
+
+ length = sizeof(ProtocolVersion) + RAN_LEN
+ + idSz + ENUM_LEN
+ + ssl->suites.suiteSz + SUITE_LEN
+ + COMP_LEN + ENUM_LEN;
+
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ length += ENUM_LEN; /* cookie */
+ sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ;
+ idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ }
+#endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, client_hello, ssl);
+
+ /* client hello, first version */
+ XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
+ idx += sizeof(ProtocolVersion);
+ ssl->chVersion = ssl->version; /* store in case changed */
+
+ /* then random */
+ if (ssl->options.connectState == CONNECT_BEGIN) {
+ RNG_GenerateBlock(&ssl->rng, output + idx, RAN_LEN);
+
+ /* store random */
+ XMEMCPY(ssl->arrays.clientRandom, output + idx, RAN_LEN);
+ } else {
+#ifdef CYASSL_DTLS
+ /* send same random on hello again */
+ XMEMCPY(output + idx, ssl->arrays.clientRandom, RAN_LEN);
+#endif
+ }
+ idx += RAN_LEN;
+
+ /* then session id */
+ output[idx++] = idSz;
+ if (idSz) {
+ XMEMCPY(output + idx, ssl->session.sessionID, ID_LEN);
+ idx += ID_LEN;
+ }
+
+ /* then DTLS cookie */
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ output[idx++] = 0;
+ }
+#endif
+ /* then cipher suites */
+ c16toa(ssl->suites.suiteSz, output + idx);
+ idx += 2;
+ XMEMCPY(output + idx, &ssl->suites.suites, ssl->suites.suiteSz);
+ idx += ssl->suites.suiteSz;
+
+ /* last, compression */
+ output[idx++] = COMP_LEN;
+ if (ssl->options.usingCompression)
+ output[idx++] = ZLIB_COMPRESSION;
+ else
+ output[idx++] = NO_COMPRESSION;
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+#endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+ }
+
+
+ static int DoHelloVerifyRequest(SSL* ssl, const byte* input,
+ word32* inOutIdx)
+ {
+ ProtocolVersion pv;
+ byte cookieSz;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("HelloVerifyRequest",
+ &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo);
+#endif
+ XMEMCPY(&pv, input + *inOutIdx, sizeof(pv));
+ *inOutIdx += sizeof(pv);
+
+ cookieSz = input[(*inOutIdx)++];
+
+ if (cookieSz)
+ *inOutIdx += cookieSz; /* skip for now */
+
+ ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+ return 0;
+ }
+
+
+ static int DoServerHello(SSL* ssl, const byte* input, word32* inOutIdx)
+ {
+ byte b;
+ byte compression;
+ ProtocolVersion pv;
+ word32 i = *inOutIdx;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
+#endif
+ XMEMCPY(&pv, input + i, sizeof(pv));
+ i += sizeof(pv);
+ XMEMCPY(ssl->arrays.serverRandom, input + i, RAN_LEN);
+ i += RAN_LEN;
+ b = input[i++];
+ if (b) {
+ XMEMCPY(ssl->arrays.sessionID, input + i, b);
+ i += b;
+ }
+ ssl->options.cipherSuite = input[++i];
+ compression = input[++i];
+ ++i; /* 2nd byte */
+
+ if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression)
+ ssl->options.usingCompression = 0; /* turn off if server refused */
+
+ ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+ *inOutIdx = i;
+
+ if (ssl->options.resuming) {
+ if (XMEMCMP(ssl->arrays.sessionID, ssl->session.sessionID, ID_LEN)
+ == 0) {
+ if (SetCipherSpecs(ssl) == 0) {
+ XMEMCPY(ssl->arrays.masterSecret, ssl->session.masterSecret,
+ SECRET_LEN);
+ if (ssl->options.tls)
+ DeriveTlsKeys(ssl);
+ else
+ DeriveKeys(ssl);
+ ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+ return 0;
+ }
+ else
+ return UNSUPPORTED_SUITE;
+ }
+ else
+ ssl->options.resuming = 0; /* server denied resumption try */
+ }
+
+ return SetCipherSpecs(ssl);
+ }
+
+
+ /* just read in and ignore for now TODO: */
+ static int DoCertificateRequest(SSL* ssl, const byte* input, word32*
+ inOutIdx)
+ {
+ word16 len;
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateRequest", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("CertificateRequest", &ssl->timeoutInfo);
+ #endif
+ len = input[(*inOutIdx)++];
+
+ /* types, read in here */
+ *inOutIdx += len;
+ ato16(&input[*inOutIdx], &len);
+ *inOutIdx += LENGTH_SZ;
+
+ /* authorities */
+ while (len) {
+ word16 dnSz;
+
+ ato16(&input[*inOutIdx], &dnSz);
+ *inOutIdx += (REQUEST_HEADER + dnSz);
+ len -= dnSz + REQUEST_HEADER;
+ }
+
+ /* don't send client cert or cert verify if user hasn't provided
+ cert and private key */
+ if (ssl->buffers.certificate.buffer && ssl->buffers.key.buffer)
+ ssl->options.sendVerify = SEND_CERT;
+ else if (IsAtLeastTLSv1_2(ssl))
+ ssl->options.sendVerify = SEND_BLANK_CERT;
+
+ return 0;
+ }
+
+
+ static int DoServerKeyExchange(SSL* ssl, const byte* input, word32*
+ inOutIdx)
+ {
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ServerKeyExchange", &ssl->timeoutInfo);
+ #endif
+
+ #ifndef NO_PSK
+ if (ssl->specs.kea == psk_kea) {
+ word16 length;
+
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+ XMEMCPY(ssl->arrays.server_hint, &input[*inOutIdx],
+ min(length, MAX_PSK_ID_LEN));
+ if (length < MAX_PSK_ID_LEN)
+ ssl->arrays.server_hint[length] = 0;
+ else
+ ssl->arrays.server_hint[MAX_PSK_ID_LEN - 1] = 0;
+ *inOutIdx += length;
+
+ return 0;
+ }
+ #endif
+ #ifdef OPENSSL_EXTRA
+ if (ssl->specs.kea == diffie_hellman_kea)
+ {
+ word16 length, verifySz, messageTotal = 6; /* pSz + gSz + pubSz */
+ byte messageVerify[MAX_DH_SZ];
+ byte* signature;
+ byte hash[FINISHED_SZ];
+ Md5 md5;
+ Sha sha;
+
+ /* p */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+ messageTotal += length;
+
+ ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap,
+ DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_P.buffer)
+ ssl->buffers.serverDH_P.length = length;
+ else
+ return MEMORY_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_P.buffer, &input[*inOutIdx], length);
+ *inOutIdx += length;
+
+ /* g */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+ messageTotal += length;
+
+ ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap,
+ DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_G.buffer)
+ ssl->buffers.serverDH_G.length = length;
+ else
+ return MEMORY_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_G.buffer, &input[*inOutIdx], length);
+ *inOutIdx += length;
+
+ /* pub */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+ messageTotal += length;
+
+ ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap,
+ DYNAMIC_TYPE_DH);
+ if (ssl->buffers.serverDH_Pub.buffer)
+ ssl->buffers.serverDH_Pub.length = length;
+ else
+ return MEMORY_ERROR;
+ XMEMCPY(ssl->buffers.serverDH_Pub.buffer, &input[*inOutIdx], length);
+ *inOutIdx += length;
+
+ /* save message for hash verify */
+ if (messageTotal > sizeof(messageVerify))
+ return BUFFER_ERROR;
+ XMEMCPY(messageVerify, &input[*inOutIdx - messageTotal], messageTotal);
+ verifySz = messageTotal;
+
+ /* signature */
+ ato16(&input[*inOutIdx], &length);
+ *inOutIdx += LENGTH_SZ;
+
+ signature = (byte*)&input[*inOutIdx];
+ *inOutIdx += length;
+
+ /* verify signature */
+
+ /* md5 */
+ InitMd5(&md5);
+ Md5Update(&md5, ssl->arrays.clientRandom, RAN_LEN);
+ Md5Update(&md5, ssl->arrays.serverRandom, RAN_LEN);
+ Md5Update(&md5, messageVerify, verifySz);
+ Md5Final(&md5, hash);
+
+ /* sha */
+ InitSha(&sha);
+ ShaUpdate(&sha, ssl->arrays.clientRandom, RAN_LEN);
+ ShaUpdate(&sha, ssl->arrays.serverRandom, RAN_LEN);
+ ShaUpdate(&sha, messageVerify, verifySz);
+ ShaFinal(&sha, &hash[MD5_DIGEST_SIZE]);
+
+ /* rsa for now */
+ {
+ int ret;
+ byte* out;
+
+ if (!ssl->peerRsaKeyPresent)
+ return NO_PEER_KEY;
+
+ ret = RsaSSL_VerifyInline(signature, length,&out, &ssl->peerRsaKey);
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ word32 sigSz;
+ byte* digest;
+ int hashType;
+ int digestSz;
+
+ /* sha1 for now */
+ digest = &hash[MD5_DIGEST_SIZE];
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+
+ sigSz = EncodeSignature(encodedSig, digest, digestSz, hashType);
+
+ if (sigSz != ret || XMEMCMP(out, encodedSig, sigSz) != 0)
+ return VERIFY_SIGN_ERROR;
+ }
+ else {
+ if (ret != sizeof(hash) || XMEMCMP(out, hash, sizeof(hash)))
+ return VERIFY_SIGN_ERROR;
+ }
+ }
+
+ ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+
+ return 0;
+ } /* dh_kea */
+ #endif /* OPENSSL_EXTRA */
+ return -1; /* not supported by build */
+ }
+
+
+ int SendClientKeyExchange(SSL* ssl)
+ {
+ byte encSecret[MAX_NTRU_ENCRYPT_SZ];
+ word32 encSz = 0;
+ word32 idx = 0;
+ int ret = 0;
+
+ if (ssl->specs.kea == rsa_kea) {
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
+ SECRET_LEN);
+ ssl->arrays.preMasterSecret[0] = ssl->chVersion.major;
+ ssl->arrays.preMasterSecret[1] = ssl->chVersion.minor;
+ ssl->arrays.preMasterSz = SECRET_LEN;
+
+ if (ssl->peerRsaKeyPresent == 0)
+ return NO_PEER_KEY;
+
+ ret = RsaPublicEncrypt(ssl->arrays.preMasterSecret, SECRET_LEN,
+ encSecret, sizeof(encSecret), &ssl->peerRsaKey,
+ &ssl->rng);
+ if (ret > 0) {
+ encSz = ret;
+ ret = 0; /* set success to 0 */
+ }
+ #ifdef OPENSSL_EXTRA
+ } else if (ssl->specs.kea == diffie_hellman_kea) {
+ buffer serverP = ssl->buffers.serverDH_P;
+ buffer serverG = ssl->buffers.serverDH_G;
+ buffer serverPub = ssl->buffers.serverDH_Pub;
+ byte priv[ENCRYPT_LEN];
+ word32 privSz;
+ DhKey key;
+
+ if (serverP.buffer == 0 || serverG.buffer == 0 ||
+ serverPub.buffer == 0)
+ return NO_PEER_KEY;
+
+ InitDhKey(&key);
+ ret = DhSetKey(&key, serverP.buffer, serverP.length,
+ serverG.buffer, serverG.length);
+ if (ret == 0)
+ /* for DH, encSecret is Yc, agree is pre-master */
+ ret = DhGenerateKeyPair(&key, &ssl->rng, priv, &privSz,
+ encSecret, &encSz);
+ if (ret == 0)
+ ret = DhAgree(&key, ssl->arrays.preMasterSecret,
+ &ssl->arrays.preMasterSz, priv, privSz,
+ serverPub.buffer, serverPub.length);
+ FreeDhKey(&key);
+ #endif /* OPENSSL_EXTRA */
+ #ifndef NO_PSK
+ } else if (ssl->specs.kea == psk_kea) {
+ byte* pms = ssl->arrays.preMasterSecret;
+
+ ssl->arrays.psk_keySz = ssl->options.client_psk_cb(ssl,
+ ssl->arrays.server_hint, ssl->arrays.client_identity,
+ MAX_PSK_ID_LEN, ssl->arrays.psk_key, MAX_PSK_KEY_LEN);
+ if (ssl->arrays.psk_keySz == 0 ||
+ ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN)
+ return PSK_KEY_ERROR;
+ encSz = (word32)XSTRLEN(ssl->arrays.client_identity);
+ if (encSz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
+ XMEMCPY(encSecret, ssl->arrays.client_identity, encSz);
+
+ /* make psk pre master secret */
+ /* length of key + length 0s + length of key + key */
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMSET(pms, 0, ssl->arrays.psk_keySz);
+ pms += ssl->arrays.psk_keySz;
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
+ ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
+ #endif /* NO_PSK */
+ #ifdef HAVE_NTRU
+ } else if (ssl->specs.kea == ntru_kea) {
+ word32 rc;
+ word16 cipherLen = sizeof(encSecret);
+ DRBG_HANDLE drbg;
+ static uint8_t const cyasslStr[] = {
+ 'C', 'y', 'a', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U'
+ };
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret,
+ SECRET_LEN);
+ ssl->arrays.preMasterSz = SECRET_LEN;
+
+ if (ssl->peerNtruKeyPresent == 0)
+ return NO_PEER_KEY;
+
+ rc = crypto_drbg_instantiate(MAX_NTRU_BITS, cyasslStr,
+ sizeof(cyasslStr), GetEntropy, &drbg);
+ if (rc != DRBG_OK)
+ return NTRU_DRBG_ERROR;
+
+ rc = crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen,ssl->peerNtruKey,
+ ssl->arrays.preMasterSz,
+ ssl->arrays.preMasterSecret,
+ &cipherLen, encSecret);
+ crypto_drbg_uninstantiate(drbg);
+ if (rc != NTRU_OK)
+ return NTRU_ENCRYPT_ERROR;
+
+ encSz = cipherLen;
+ ret = 0;
+ #endif /* HAVE_NTRU */
+ } else
+ return -1; /* unsupported kea */
+
+ if (ret == 0) {
+ byte *output;
+ int sendSz;
+ word32 tlsSz = 0;
+
+ if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea)
+ tlsSz = 2;
+
+ sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA;
+ }
+ #endif
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl);
+
+ if (tlsSz) {
+ c16toa((word16)encSz, &output[idx]);
+ idx += 2;
+ }
+ XMEMCPY(output + idx, encSecret, encSz);
+ idx += encSz;
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo,
+ output, sendSz, ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ ret = SendBuffered(ssl);
+ }
+
+ if (ret == 0 || ret == WANT_WRITE) {
+ int tmpRet = MakeMasterSecret(ssl);
+ if (tmpRet != 0)
+ ret = tmpRet; /* save WANT_WRITE unless more serious */
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ }
+
+ return ret;
+ }
+
+ int SendCertificateVerify(SSL* ssl)
+ {
+ byte *output;
+ int sendSz = 0, length, ret;
+ word32 idx = 0;
+ RsaKey key;
+
+ if (ssl->options.sendVerify == SEND_BLANK_CERT)
+ return 0; /* sent blank cert, can't verify */
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, MAX_CERT_VERIFY_SZ)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ BuildCertHashes(ssl, &ssl->certHashes);
+
+ /* TODO: when add DSS support check here */
+ InitRsaKey(&key, ssl->heap);
+ ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
+ ssl->buffers.key.length);
+ if (ret == 0) {
+ byte* verify = (byte*)&output[RECORD_HEADER_SZ +
+ HANDSHAKE_HEADER_SZ];
+ byte* signBuffer = ssl->certHashes.md5;
+ word32 signSz = sizeof(Hashes);
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+ length = RsaEncryptSize(&key);
+ c16toa((word16)length, verify); /* prepend verify header */
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ byte* digest;
+ int hashType;
+ int digestSz;
+
+ /* sha1 for now */
+ digest = ssl->certHashes.sha;
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+
+ signSz = EncodeSignature(encodedSig, digest, digestSz,hashType);
+ signBuffer = encodedSig;
+ }
+
+ ret = RsaSSL_Sign(signBuffer, signSz, verify +
+ VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);
+
+ if (ret > 0) {
+ ret = 0; /* reset */
+
+ AddHeaders(output, length + VERIFY_HEADER, certificate_verify,
+ ssl);
+
+ sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length +
+ VERIFY_HEADER;
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+ HashOutput(ssl, output, sendSz, 0);
+ }
+ }
+
+ FreeRsaKey(&key);
+
+ if (ret == 0) {
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateVerify", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("CertificateVerify", &ssl->timeoutInfo,
+ output, sendSz, ssl->heap);
+ #endif
+ ssl->buffers.outputBuffer.length += sendSz;
+ return SendBuffered(ssl);
+ }
+ else
+ return ret;
+ }
+
+
+
+#endif /* NO_CYASSL_CLIENT */
+
+
+#ifndef NO_CYASSL_SERVER
+
+ int SendServerHello(SSL* ssl)
+ {
+ byte *output;
+ word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ int ret;
+
+ length = sizeof(ProtocolVersion) + RAN_LEN
+ + ID_LEN + ENUM_LEN
+ + SUITE_LEN
+ + ENUM_LEN;
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, MAX_HELLO_SZ)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+ AddHeaders(output, length, server_hello, ssl);
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ /* now write to output */
+ /* first version */
+ XMEMCPY(output + idx, &ssl->version, sizeof(ProtocolVersion));
+ idx += sizeof(ProtocolVersion);
+
+ /* then random */
+ if (!ssl->options.resuming)
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
+ XMEMCPY(output + idx, ssl->arrays.serverRandom, RAN_LEN);
+ idx += RAN_LEN;
+
+#ifdef SHOW_SECRETS
+ {
+ int j;
+ printf("server random: ");
+ for (j = 0; j < RAN_LEN; j++)
+ printf("%02x", ssl->arrays.serverRandom[j]);
+ printf("\n");
+ }
+#endif
+ /* then session id */
+ output[idx++] = ID_LEN;
+ if (!ssl->options.resuming)
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.sessionID, ID_LEN);
+ XMEMCPY(output + idx, ssl->arrays.sessionID, ID_LEN);
+ idx += ID_LEN;
+
+ /* then cipher suite */
+ output[idx++] = 0x00;
+ output[idx++] = ssl->options.cipherSuite;
+
+ /* last, compression */
+ if (ssl->options.usingCompression)
+ output[idx++] = ZLIB_COMPRESSION;
+ else
+ output[idx++] = NO_COMPRESSION;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+ #endif
+
+ ssl->options.serverState = SERVER_HELLO_COMPLETE;
+
+ return SendBuffered(ssl);
+ }
+
+ int SendServerKeyExchange(SSL* ssl)
+ {
+ int ret = 0;
+
+ if (ssl->specs.kea != psk_kea) return 0;
+
+ #ifndef NO_PSK
+ {
+ byte *output;
+ word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int sendSz;
+ if (ssl->arrays.server_hint[0] == 0) return 0; /* don't send */
+
+ /* include size part */
+ length = (word32)XSTRLEN(ssl->arrays.server_hint);
+ if (length > MAX_PSK_ID_LEN) return SERVER_HINT_ERROR;
+ length += + HINT_LEN_SZ;
+ sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ }
+ #endif
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, server_key_exchange, ssl);
+
+ /* key data */
+ c16toa((word16)(length - HINT_LEN_SZ), output + idx);
+ idx += HINT_LEN_SZ;
+ XMEMCPY(output + idx, ssl->arrays.server_hint, length - HINT_LEN_SZ);
+
+ HashOutput(ssl, output, sendSz, 0);
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo,
+ output, sendSz, ssl->heap);
+ #endif
+
+ ssl->buffers.outputBuffer.length += sendSz;
+ ret = SendBuffered(ssl);
+ ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
+ }
+ #endif /*NO_PSK */
+
+ return ret;
+ }
+
+
+ static int MatchSuite(SSL* ssl, Suites* peerSuites)
+ {
+ word16 i, j;
+
+ /* & 0x1 equivalent % 2 */
+ if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1)
+ return MATCH_SUITE_ERROR;
+
+ /* start with best, if a match we are good, Ciphers are at odd index
+ since all SSL and TLS ciphers have 0x00 first byte */
+ for (i = 1; i < ssl->suites.suiteSz; i += 2)
+ for (j = 1; j < peerSuites->suiteSz; j += 2)
+ if (ssl->suites.suites[i] == peerSuites->suites[j]) {
+ ssl->options.cipherSuite = ssl->suites.suites[i];
+ return SetCipherSpecs(ssl);
+ }
+
+ return MATCH_SUITE_ERROR;
+ }
+
+
+ /* process alert, return level */
+ int ProcessOldClientHello(SSL* ssl, const byte* input, word32* inOutIdx,
+ word32 inSz, word16 sz)
+ {
+ word32 idx = *inOutIdx;
+ word16 sessionSz;
+ word16 randomSz;
+ word16 i, j;
+ ProtocolVersion pv;
+ Suites clSuites;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ClientHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+
+ /* manually hash input since different format */
+ Md5Update(&ssl->hashMd5, input + idx, sz);
+ ShaUpdate(&ssl->hashSha, input + idx, sz);
+
+ /* does this value mean client_hello? */
+ idx++;
+
+ /* version */
+ pv.major = input[idx++];
+ pv.minor = input[idx++];
+ ssl->chVersion = pv; /* store */
+
+ if (ssl->version.minor > 0 && pv.minor == 0) {
+ if (!ssl->options.downgrade)
+ return VERSION_ERROR;
+ /* turn off tls */
+ ssl->options.tls = 0;
+ ssl->options.tls1_1 = 0;
+ ssl->version.minor = 0;
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, FALSE,
+ ssl->options.haveNTRU);
+ }
+
+ /* suite size */
+ ato16(&input[idx], &clSuites.suiteSz);
+ idx += 2;
+
+ if (clSuites.suiteSz > MAX_SUITE_SZ)
+ return BUFFER_ERROR;
+
+ /* session size */
+ ato16(&input[idx], &sessionSz);
+ idx += 2;
+
+ if (sessionSz > ID_LEN)
+ return BUFFER_ERROR;
+
+ /* random size */
+ ato16(&input[idx], &randomSz);
+ idx += 2;
+
+ if (randomSz > RAN_LEN)
+ return BUFFER_ERROR;
+
+ /* suites */
+ for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) {
+ byte first = input[idx++];
+ if (!first) { /* implicit: skip sslv2 type */
+ XMEMCPY(&clSuites.suites[j], &input[idx], 2);
+ j += 2;
+ }
+ idx += 2;
+ }
+ clSuites.suiteSz = j;
+
+ /* session id */
+ if (sessionSz) {
+ XMEMCPY(ssl->arrays.sessionID, input + idx, sessionSz);
+ idx += sessionSz;
+ ssl->options.resuming = 1;
+ }
+
+ /* random */
+ if (randomSz < RAN_LEN)
+ XMEMSET(ssl->arrays.clientRandom, 0, RAN_LEN - randomSz);
+ XMEMCPY(&ssl->arrays.clientRandom[RAN_LEN - randomSz], input + idx,
+ randomSz);
+ idx += randomSz;
+
+ if (ssl->options.usingCompression)
+ ssl->options.usingCompression = 0; /* turn off */
+
+ ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+ *inOutIdx = idx;
+
+ /* DoClientHello uses same resume code */
+ while (ssl->options.resuming) { /* let's try */
+ SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
+ if (!session) {
+ ssl->options.resuming = 0;
+ break; /* session lookup failed */
+ }
+ if (MatchSuite(ssl, &clSuites) < 0)
+ return UNSUPPORTED_SUITE;
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
+ if (ssl->options.tls)
+ DeriveTlsKeys(ssl);
+ else
+ DeriveKeys(ssl);
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+
+ return 0;
+ }
+
+ return MatchSuite(ssl, &clSuites);
+ }
+
+
+ static int DoClientHello(SSL* ssl, const byte* input, word32* inOutIdx,
+ word32 totalSz, word32 helloSz)
+ {
+ byte b;
+ ProtocolVersion pv;
+ Suites clSuites;
+ word32 i = *inOutIdx;
+ word32 begin = i;
+
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo);
+ if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
+#endif
+ /* make sure can read up to session */
+ if (i + sizeof(pv) + RAN_LEN + ENUM_LEN > totalSz)
+ return INCOMPLETE_DATA;
+
+ XMEMCPY(&pv, input + i, sizeof(pv));
+ ssl->chVersion = pv; /* store */
+ i += sizeof(pv);
+ if (ssl->version.minor > 0 && pv.minor == 0) {
+ if (!ssl->options.downgrade)
+ return VERSION_ERROR;
+ /* turn off tls */
+ ssl->options.tls = 0;
+ ssl->options.tls1_1 = 0;
+ ssl->version.minor = 0;
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, FALSE,
+ ssl->options.haveNTRU);
+ }
+ /* random */
+ XMEMCPY(ssl->arrays.clientRandom, input + i, RAN_LEN);
+ i += RAN_LEN;
+
+#ifdef SHOW_SECRETS
+ {
+ int j;
+ printf("client random: ");
+ for (j = 0; j < RAN_LEN; j++)
+ printf("%02x", ssl->arrays.clientRandom[j]);
+ printf("\n");
+ }
+#endif
+ /* session id */
+ b = input[i++];
+ if (b) {
+ if (i + ID_LEN > totalSz)
+ return INCOMPLETE_DATA;
+ XMEMCPY(ssl->arrays.sessionID, input + i, ID_LEN);
+ i += b;
+ ssl->options.resuming= 1; /* client wants to resume */
+ }
+
+ #ifdef CYASSL_DTLS
+ /* cookie */
+ if (ssl->options.dtls) {
+ b = input[i++];
+ if (b) {
+ if (b > MAX_COOKIE_LEN)
+ return BUFFER_ERROR;
+ if (i + b > totalSz)
+ return INCOMPLETE_DATA;
+ XMEMCPY(ssl->arrays.cookie, input + i, b);
+ i += b;
+ }
+ }
+ #endif
+
+ if (i + LENGTH_SZ > totalSz)
+ return INCOMPLETE_DATA;
+ /* suites */
+ ato16(&input[i], &clSuites.suiteSz);
+ i += 2;
+
+ /* suites and comp len */
+ if (i + clSuites.suiteSz + ENUM_LEN > totalSz)
+ return INCOMPLETE_DATA;
+ if (clSuites.suiteSz > MAX_SUITE_SZ)
+ return BUFFER_ERROR;
+ XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz);
+ i += clSuites.suiteSz;
+
+ b = input[i++]; /* comp len */
+ if (i + b > totalSz)
+ return INCOMPLETE_DATA;
+
+ if (ssl->options.usingCompression) {
+ int match = 0;
+ while (b--) {
+ byte comp = input[i++];
+ if (comp == ZLIB_COMPRESSION)
+ match = 1;
+ }
+ if (!match)
+ ssl->options.usingCompression = 0; /* turn off */
+ }
+ else
+ i += b; /* ignore, since we're not on */
+
+ ssl->options.clientState = CLIENT_HELLO_COMPLETE;
+
+ *inOutIdx = i;
+ if ( (i - begin) < helloSz)
+ *inOutIdx = begin + helloSz; /* skip extensions */
+
+ /* ProcessOld uses same resume code */
+ while (ssl->options.resuming) { /* let's try */
+ SSL_SESSION* session = GetSession(ssl, ssl->arrays.masterSecret);
+ if (!session) {
+ ssl->options.resuming = 0;
+ break; /* session lookup failed */
+ }
+ if (MatchSuite(ssl, &clSuites) < 0)
+ return UNSUPPORTED_SUITE;
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN);
+ if (ssl->options.tls)
+ DeriveTlsKeys(ssl);
+ else
+ DeriveKeys(ssl);
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+
+ return 0;
+ }
+ return MatchSuite(ssl, &clSuites);
+ }
+
+
+ static int DoCertificateVerify(SSL* ssl, byte* input, word32* inOutsz,
+ word32 totalSz)
+ {
+ word16 sz = 0;
+ word32 i = *inOutsz;
+ int ret = VERIFY_CERT_ERROR; /* start in error state */
+ byte* sig;
+ byte* out;
+ int outLen;
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("CertificateVerify", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("CertificateVerify", &ssl->timeoutInfo);
+ #endif
+ if ( (i + VERIFY_HEADER) > totalSz)
+ return INCOMPLETE_DATA;
+
+ ato16(&input[i], &sz);
+ i += VERIFY_HEADER;
+
+ if ( (i + sz) > totalSz)
+ return INCOMPLETE_DATA;
+
+ if (sz > ENCRYPT_LEN)
+ return BUFFER_ERROR;
+
+ sig = &input[i];
+ *inOutsz = i + sz;
+ /* TODO: when add DSS support check here */
+ if (ssl->peerRsaKeyPresent != 0) {
+ outLen = RsaSSL_VerifyInline(sig, sz, &out, &ssl->peerRsaKey);
+
+ if (IsAtLeastTLSv1_2(ssl)) {
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ word32 sigSz;
+ byte* digest;
+ int hashType;
+ int digestSz;
+
+ /* sha1 for now */
+ digest = ssl->certHashes.sha;
+ hashType = SHAh;
+ digestSz = SHA_DIGEST_SIZE;
+
+ sigSz = EncodeSignature(encodedSig, digest, digestSz, hashType);
+
+ if (outLen == sigSz && XMEMCMP(out, encodedSig, sigSz) == 0)
+ ret = 0;
+ }
+ else {
+ if (outLen == sizeof(ssl->certHashes) && XMEMCMP(out,
+ ssl->certHashes.md5, sizeof(ssl->certHashes)) == 0)
+ ret = 0;
+ }
+ }
+ return ret;
+ }
+
+
+ int SendServerHelloDone(SSL* ssl)
+ {
+ byte *output;
+ int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
+ int ret;
+
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
+ #endif
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, 0, server_hello_done, ssl);
+
+ HashOutput(ssl, output, sendSz, 0);
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ServerHelloDone", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz,
+ ssl->heap);
+#endif
+ ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+ }
+
+
+ int SendHelloVerifyRequest(SSL* ssl)
+ {
+ byte* output;
+ int length = VERSION_SZ + ENUM_LEN;
+ int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ;
+ int sendSz = length + idx;
+ int ret;
+
+ /* check for avalaible size */
+ if ((ret = CheckAvalaibleSize(ssl, sendSz)) != 0)
+ return ret;
+
+ /* get ouput buffer */
+ output = ssl->buffers.outputBuffer.buffer +
+ ssl->buffers.outputBuffer.idx;
+
+ AddHeaders(output, length, hello_verify_request, ssl);
+
+ XMEMCPY(output + idx, &ssl->chVersion, VERSION_SZ);
+ idx += VERSION_SZ;
+ output[idx++] = 0; /* no cookie for now */
+
+ HashOutput(ssl, output, sendSz, 0);
+#ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("HelloVerifyRequest", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddPacketInfo("HelloVerifyRequest", &ssl->timeoutInfo, output,
+ sendSz, ssl->heap);
+#endif
+ ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+
+ ssl->buffers.outputBuffer.length += sendSz;
+
+ return SendBuffered(ssl);
+ }
+
+
+ static int DoClientKeyExchange(SSL* ssl, byte* input,
+ word32* inOutIdx)
+ {
+ int ret = 0;
+ word32 length = 0;
+ byte* out;
+
+ if (ssl->options.verifyPeer && ssl->options.failNoCert)
+ if (!ssl->options.havePeerCert) {
+ CYASSL_MSG("client didn't present peer cert");
+ return NO_PEER_CERT;
+ }
+
+ #ifdef CYASSL_CALLBACKS
+ if (ssl->hsInfoOn)
+ AddPacketName("ClientKeyExchange", &ssl->handShakeInfo);
+ if (ssl->toInfoOn)
+ AddLateName("ClientKeyExchange", &ssl->timeoutInfo);
+ #endif
+ if (ssl->specs.kea == rsa_kea) {
+ word32 idx = 0;
+ RsaKey key;
+ byte* tmp = 0;
+
+ InitRsaKey(&key, ssl->heap);
+
+ if (ssl->buffers.key.buffer)
+ ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key,
+ ssl->buffers.key.length);
+ else
+ return NO_PRIVATE_KEY;
+
+ if (ret == 0) {
+ length = RsaEncryptSize(&key);
+ ssl->arrays.preMasterSz = SECRET_LEN;
+
+ if (ssl->options.tls)
+ (*inOutIdx) += 2;
+ tmp = input + *inOutIdx;
+ *inOutIdx += length;
+
+ if (RsaPrivateDecryptInline(tmp, length, &out, &key) ==
+ SECRET_LEN) {
+ XMEMCPY(ssl->arrays.preMasterSecret, out, SECRET_LEN);
+ if (ssl->arrays.preMasterSecret[0] != ssl->chVersion.major
+ ||
+ ssl->arrays.preMasterSecret[1] != ssl->chVersion.minor)
+
+ ret = PMS_VERSION_ERROR;
+ else
+ ret = MakeMasterSecret(ssl);
+ }
+ else
+ ret = RSA_PRIVATE_ERROR;
+ }
+
+ FreeRsaKey(&key);
+#ifndef NO_PSK
+ } else if (ssl->specs.kea == psk_kea) {
+ byte* pms = ssl->arrays.preMasterSecret;
+ word16 ci_sz;
+
+ ato16(&input[*inOutIdx], &ci_sz);
+ *inOutIdx += LENGTH_SZ;
+ if (ci_sz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
+
+ XMEMCPY(ssl->arrays.client_identity, &input[*inOutIdx], ci_sz);
+ *inOutIdx += ci_sz;
+ ssl->arrays.client_identity[ci_sz] = 0;
+
+ ssl->arrays.psk_keySz = ssl->options.server_psk_cb(ssl,
+ ssl->arrays.client_identity, ssl->arrays.psk_key,
+ MAX_PSK_KEY_LEN);
+ if (ssl->arrays.psk_keySz == 0 ||
+ ssl->arrays.psk_keySz > MAX_PSK_KEY_LEN) return PSK_KEY_ERROR;
+
+ /* make psk pre master secret */
+ /* length of key + length 0s + length of key + key */
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMSET(pms, 0, ssl->arrays.psk_keySz);
+ pms += ssl->arrays.psk_keySz;
+ c16toa((word16)ssl->arrays.psk_keySz, pms);
+ pms += 2;
+ XMEMCPY(pms, ssl->arrays.psk_key, ssl->arrays.psk_keySz);
+ ssl->arrays.preMasterSz = ssl->arrays.psk_keySz * 2 + 4;
+
+ ret = MakeMasterSecret(ssl);
+#endif /* NO_PSK */
+#ifdef HAVE_NTRU
+ } else if (ssl->specs.kea == ntru_kea) {
+ word32 rc;
+ word16 cipherLen;
+ word16 plainLen = sizeof(ssl->arrays.preMasterSecret);
+ byte* tmp;
+
+ if (!ssl->buffers.key.buffer)
+ return NO_PRIVATE_KEY;
+
+ ato16(&input[*inOutIdx], &cipherLen);
+ *inOutIdx += LENGTH_SZ;
+ if (cipherLen > MAX_NTRU_ENCRYPT_SZ)
+ return NTRU_KEY_ERROR;
+
+ tmp = input + *inOutIdx;
+ rc = crypto_ntru_decrypt((word16)ssl->buffers.key.length,
+ ssl->buffers.key.buffer, cipherLen, tmp, &plainLen,
+ ssl->arrays.preMasterSecret);
+
+ if (rc != NTRU_OK || plainLen != SECRET_LEN)
+ return NTRU_DECRYPT_ERROR;
+ *inOutIdx += cipherLen;
+
+ ssl->arrays.preMasterSz = plainLen;
+ ret = MakeMasterSecret(ssl);
+#endif /* HAVE_NTRU */
+ }
+
+ if (ret == 0) {
+ ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
+ if (ssl->options.verifyPeer)
+ BuildCertHashes(ssl, &ssl->certHashes);
+ }
+
+ return ret;
+ }
+
+#endif /* NO_CYASSL_SERVER */
+
+
+#ifdef SINGLE_THREADED
+
+int InitMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+
+int FreeMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+
+int LockMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+
+int UnLockMutex(CyaSSL_Mutex* m)
+{
+ return 0;
+}
+
+#else /* MULTI_THREAD */
+
+ #ifdef USE_WINDOWS_API
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ InitializeCriticalSection(m);
+ return 0;
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ DeleteCriticalSection(m);
+ return 0;
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ EnterCriticalSection(m);
+ return 0;
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ LeaveCriticalSection(m);
+ return 0;
+ }
+
+ #elif defined(CYASSL_PTHREADS)
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_init(m, 0) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_destroy(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_lock(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ if (pthread_mutex_unlock(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+ #elif defined(THREADX)
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_create(m, "CyaSSL Mutex", TX_NO_INHERIT) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_delete(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ if (tx_mutex_put(m) == 0)
+ return 0;
+ else
+ return -1;
+ }
+
+ #elif defined(MICRIUM)
+
+ int InitMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_MutexCreate(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+ }
+
+
+ int FreeMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_FreeMutex(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+ }
+
+
+ int LockMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_LockMutex(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+ }
+
+
+ int UnLockMutex(CyaSSL_Mutex* m)
+ {
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ if (NetSecure_OS_UnLockMutex(m) == 0)
+ return 0;
+ else
+ return -1;
+ #else
+ return 0;
+ #endif
+
+ }
+
+ #endif /* USE_WINDOWS_API */
+#endif /* SINGLE_THREADED */
+
+
+#ifdef DEBUG_CYASSL
+
+ static int logging = 0;
+
+
+ int CyaSSL_Debugging_ON(void)
+ {
+ logging = 1;
+ return 0;
+ }
+
+
+ void CyaSSL_Debugging_OFF(void)
+ {
+ logging = 0;
+ }
+
+
+#ifdef THREADX
+ int dc_log_printf(char*, ...);
+#endif
+
+ void CYASSL_MSG(const char* msg)
+ {
+ if (logging) {
+#ifdef THREADX
+ dc_log_printf("%s\n", msg);
+#elif defined(MICRIUM)
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ NetSecure_TraceOut((CPU_CHAR *)msg);
+ #endif
+#else
+ fprintf(stderr, "%s\n", msg);
+#endif
+ }
+ }
+
+
+ void CYASSL_ENTER(const char* msg)
+ {
+ if (logging) {
+ char buffer[80];
+ sprintf(buffer, "CyaSSL Entering %s", msg);
+ CYASSL_MSG(buffer);
+ }
+ }
+
+
+ void CYASSL_LEAVE(const char* msg, int ret)
+ {
+ if (logging) {
+ char buffer[80];
+ sprintf(buffer, "CyaSSL Leaving %s, return %d", msg, ret);
+ CYASSL_MSG(buffer);
+ }
+ }
+
+
+ void CYASSL_ERROR(int error)
+ {
+ if (logging) {
+ char buffer[80];
+ sprintf(buffer, "CyaSSL error occured, error = %d", error);
+ CYASSL_MSG(buffer);
+ }
+ }
+
+
+#else /* DEBUG_CYASSL */
+
+ int CyaSSL_Debugging_ON(void)
+ {
+ return -1; /* not compiled in */
+ }
+
+
+ void CyaSSL_Debugging_OFF(void)
+ {
+ /* already off */
+ }
+
+#endif /* DEBUG_CYASSL */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cyassl_int.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,1141 @@
+/* cyassl_int.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+#ifndef CYASSL_INT_H
+#define CYASSL_INT_H
+
+
+#include "types.h"
+#include "random.h"
+#include "des3.h"
+#include "hc128.h"
+#include "rabbit.h"
+#include "asn.h"
+#include "ctc_md5.h"
+#include "ctc_aes.h"
+
+#ifdef CYASSL_CALLBACKS
+ #include "cyassl_callbacks.h"
+ #include <signal.h>
+#endif
+
+#ifdef USE_WINDOWS_API
+ #include <windows.h>
+#elif defined(THREADX)
+ #ifndef SINGLE_THREADED
+ #include "tx_api.h"
+ #endif
+#elif defined(MICRIUM)
+ /* do nothing, just don't pick Unix */
+#else
+ #ifndef SINGLE_THREADED
+ #define CYASSL_PTHREADS
+ #include <pthread.h>
+ #endif
+ #if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
+ #include <unistd.h> /* for close of BIO */
+ #endif
+#endif
+
+#ifdef HAVE_LIBZ
+ #include "zlib.h"
+#endif
+
+#ifdef _MSC_VER
+ /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
+ #pragma warning(disable: 4996)
+#endif
+
+#ifdef NO_AES
+ #if !defined (ALIGN16)
+ #define ALIGN16
+ #endif
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#ifdef USE_WINDOWS_API
+ typedef unsigned int SOCKET_T;
+#else
+ typedef int SOCKET_T;
+#endif
+
+
+typedef byte word24[3];
+
+/* Define or comment out the cipher suites you'd like to be compiled in
+ make sure to use at least one BUILD_SSL_xxx or BUILD_TLS_xxx is defined
+
+ When adding cipher suites, add name to cipher_names, idx to cipher_name_idx
+*/
+#ifndef NO_RC4
+ #define BUILD_SSL_RSA_WITH_RC4_128_SHA
+ #define BUILD_SSL_RSA_WITH_RC4_128_MD5
+ #if !defined(NO_TLS) && defined(HAVE_NTRU)
+ #define BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ #endif
+#endif
+
+#ifndef NO_DES3
+ #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ #if !defined(NO_TLS) && defined(HAVE_NTRU)
+ #define BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ #endif
+#endif
+
+#if !defined(NO_AES) && !defined(NO_TLS)
+ #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ #if !defined (NO_PSK)
+ #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ #endif
+ #if defined(HAVE_NTRU)
+ #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ #endif
+#endif
+
+#if !defined(NO_HC128) && !defined(NO_TLS)
+ #define BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ #define BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+#endif
+
+#if !defined(NO_RABBIT) && !defined(NO_TLS)
+ #define BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+#endif
+
+#if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && defined(OPENSSL_EXTRA)
+ #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+#endif
+
+
+
+#if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \
+ defined(BUILD_SSL_RSA_WITH_RC4_128_MD5)
+ #define BUILD_ARC4
+#endif
+
+#if defined(BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA)
+ #define BUILD_DES3
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_AES_128_CBC_SHA) || \
+ defined(BUILD_TLS_RSA_WITH_AES_256_CBC_SHA)
+ #define BUILD_AES
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_HC_128_CBC_SHA) || \
+ defined(BUILD_TLS_RSA_WITH_HC_128_CBC_MD5)
+ #define BUILD_HC128
+#endif
+
+#if defined(BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA)
+ #define BUILD_RABBIT
+#endif
+
+#ifdef NO_DES3
+ #define DES_BLOCK_SIZE 8
+#endif
+
+#ifdef NO_AES
+ #define AES_BLOCK_SIZE 16
+#endif
+
+
+/* actual cipher values, 2nd byte */
+enum {
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x39,
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x33,
+ TLS_RSA_WITH_AES_256_CBC_SHA = 0x35,
+ TLS_RSA_WITH_AES_128_CBC_SHA = 0x2F,
+ TLS_PSK_WITH_AES_256_CBC_SHA = 0x8d,
+ TLS_PSK_WITH_AES_128_CBC_SHA = 0x8c,
+ SSL_RSA_WITH_RC4_128_SHA = 0x05,
+ SSL_RSA_WITH_RC4_128_MD5 = 0x04,
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA = 0x0A,
+
+ /* CyaSSL extension - eSTRAM */
+ TLS_RSA_WITH_HC_128_CBC_MD5 = 0xFB,
+ TLS_RSA_WITH_HC_128_CBC_SHA = 0xFC,
+ TLS_RSA_WITH_RABBIT_CBC_SHA = 0xFD,
+
+ /* CyaSSL extension - NTRU */
+ TLS_NTRU_RSA_WITH_RC4_128_SHA = 0x65,
+ TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA = 0x66,
+ TLS_NTRU_RSA_WITH_AES_128_CBC_SHA = 0x67,
+ TLS_NTRU_RSA_WITH_AES_256_CBC_SHA = 0x68
+};
+
+
+enum Misc {
+ SERVER_END = 0,
+ CLIENT_END,
+
+ SEND_CERT = 1,
+ SEND_BLANK_CERT = 2,
+
+ DTLS_MAJOR = 0xfe, /* DTLS major version number */
+ DTLS_MINOR = 0xff, /* DTLS minor version number */
+ SSLv3_MAJOR = 3, /* SSLv3 and TLSv1+ major version number */
+ SSLv3_MINOR = 0, /* TLSv1 minor version number */
+ TLSv1_MINOR = 1, /* TLSv1 minor version number */
+ TLSv1_1_MINOR = 2, /* TLSv1_1 minor version number */
+ TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */
+ NO_COMPRESSION = 0,
+ ZLIB_COMPRESSION = 221, /* CyaSSL zlib compression */
+ SECRET_LEN = 48, /* pre RSA and all master */
+ ENCRYPT_LEN = 256, /* allow 2048 bit static buffer */
+ SIZEOF_SENDER = 4, /* clnt or srvr */
+ FINISHED_SZ = MD5_DIGEST_SIZE + SHA_DIGEST_SIZE,
+ MAX_RECORD_SIZE = 16384, /* 2^14, max size by standard */
+ MAX_UDP_SIZE = 1400, /* don't exceed MTU */
+ MAX_MSG_EXTRA = 68, /* max added to msg, mac + pad */
+ MAX_COMP_EXTRA = 1024, /* max compression extra */
+ MAX_MTU = 1500, /* max expected MTU */
+ MAX_DH_SZ = 612, /* 2240 p, pub, g + 2 byte size for each */
+ MAX_STR_VERSION = 8, /* string rep of protocol version */
+
+ PAD_MD5 = 48, /* pad length for finished */
+ PAD_SHA = 40, /* pad length for finished */
+ PEM_LINE_LEN = 80, /* PEM line max + fudge */
+ LENGTH_SZ = 2, /* length field for HMAC, data only */
+ VERSION_SZ = 2, /* length of proctocol version */
+ SEQ_SZ = 8, /* 64 bit sequence number */
+ BYTE3_LEN = 3, /* up to 24 bit byte lengths */
+ ALERT_SIZE = 2, /* level + description */
+ REQUEST_HEADER = 2, /* always use 2 bytes */
+ VERIFY_HEADER = 2, /* always use 2 bytes */
+
+ MAX_SUITE_SZ = 128, /* only 64 suites for now! */
+ RAN_LEN = 32, /* random length */
+ SEED_LEN = RAN_LEN * 2, /* tls prf seed length */
+ ID_LEN = 32, /* session id length */
+ MAX_COOKIE_LEN = 32, /* max dtls cookie size */
+ SUITE_LEN = 2, /* cipher suite sz length */
+ ENUM_LEN = 1, /* always a byte */
+ COMP_LEN = 1, /* compression length */
+
+ HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */
+ RECORD_HEADER_SZ = 5, /* type + version + len(2) */
+ CERT_HEADER_SZ = 3, /* always 3 bytes */
+ REQ_HEADER_SZ = 2, /* cert request header sz */
+ HINT_LEN_SZ = 2, /* length of hint size field */
+
+ DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */
+ DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */
+ DTLS_HANDSHAKE_EXTRA = 8, /* diff from normal */
+ DTLS_RECORD_EXTRA = 8, /* diff from normal */
+
+ FINISHED_LABEL_SZ = 15, /* TLS finished label size */
+ TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
+ MASTER_LABEL_SZ = 13, /* TLS master secret label sz */
+ KEY_LABEL_SZ = 13, /* TLS key block expansion sz */
+ MAX_PRF_HALF = 128, /* Maximum half secret len */
+ MAX_PRF_LABSEED = 80, /* Maximum label + seed len */
+ MAX_PRF_DIG = 148, /* Maximum digest len */
+ MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */
+ SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */
+
+ RC4_KEY_SIZE = 16, /* always 128bit */
+ DES_KEY_SIZE = 8, /* des */
+ DES3_KEY_SIZE = 24, /* 3 des ede */
+ DES_IV_SIZE = DES_BLOCK_SIZE,
+ AES_256_KEY_SIZE = 32, /* for 256 bit */
+ AES_192_KEY_SIZE = 24, /* for 192 bit */
+ AES_IV_SIZE = 16, /* always block size */
+ AES_128_KEY_SIZE = 16, /* for 128 bit */
+
+ HC_128_KEY_SIZE = 16, /* 128 bits */
+ HC_128_IV_SIZE = 16, /* also 128 bits */
+
+ RABBIT_KEY_SIZE = 16, /* 128 bits */
+ RABBIT_IV_SIZE = 8, /* 64 bits for iv */
+
+ EVP_SALT_SIZE = 8, /* evp salt size 64 bits */
+
+ MAX_HELLO_SZ = 128, /* max client or server hello */
+ MAX_CERT_VERIFY_SZ = 1024, /* max */
+ CLIENT_HELLO_FIRST = 35, /* Protocol + RAN_LEN + sizeof(id_len) */
+ MAX_SUITE_NAME = 48, /* maximum length of cipher suite string */
+ DEFAULT_TIMEOUT = 500, /* default resumption timeout in seconds */
+
+ MAX_PSK_ID_LEN = 128, /* max psk identity/hint supported */
+ MAX_PSK_KEY_LEN = 64, /* max psk key supported */
+
+ MAX_CHAIN_DEPTH = 4, /* max cert chain peer depth */
+ MAX_X509_SIZE = 2048, /* max static x509 buffer size */
+ FILE_BUFFER_SIZE = 1024, /* default static file buffer size for input,
+ will use dynamic buffer if not big enough */
+
+ MAX_NTRU_PUB_KEY_SZ = 1027, /* NTRU max for now */
+ MAX_NTRU_ENCRYPT_SZ = 1027, /* NTRU max for now */
+ MAX_NTRU_BITS = 256, /* max symmetric bit strength */
+ NO_SNIFF = 0, /* not sniffing */
+ SNIFF = 1, /* currently sniffing */
+
+ NO_COPY = 0, /* should we copy static buffer for write */
+ COPY = 1 /* should we copy static buffer for write */
+};
+
+
+/* states */
+enum states {
+ NULL_STATE = 0,
+
+ SERVER_HELLOVERIFYREQUEST_COMPLETE,
+ SERVER_HELLO_COMPLETE,
+ SERVER_CERT_COMPLETE,
+ SERVER_KEYEXCHANGE_COMPLETE,
+ SERVER_HELLODONE_COMPLETE,
+ SERVER_FINISHED_COMPLETE,
+
+ CLIENT_HELLO_COMPLETE,
+ CLIENT_KEYEXCHANGE_COMPLETE,
+ CLIENT_FINISHED_COMPLETE,
+
+ HANDSHAKE_DONE
+};
+
+
+#ifndef SSL_TYPES_DEFINED
+ typedef struct SSL_METHOD SSL_METHOD;
+ typedef struct SSL_CTX SSL_CTX;
+ typedef struct SSL_SESSION SSL_SESSION;
+ typedef struct SSL_CIPHER SSL_CIPHER;
+ typedef struct SSL SSL;
+ typedef struct X509 X509;
+ typedef struct X509_CHAIN X509_CHAIN;
+ typedef struct BIO BIO;
+ typedef struct BIO_METHOD BIO_METHOD;
+
+ #undef X509_NAME
+ typedef struct X509_NAME X509_NAME;
+
+ typedef struct X509_STORE_CTX {
+ int error;
+ int error_depth;
+ X509* current_cert; /* stunnel dereference */
+ char* domain; /* subject CN domain name */
+ } X509_STORE_CTX;
+
+
+ typedef int (*pem_password_cb)(char*, int, int, void*);
+ typedef int (*CallbackIORecv)(char *buf, int sz, void *ctx);
+ typedef int (*CallbackIOSend)(char *buf, int sz, void *ctx);
+ typedef int (*VerifyCallback)(int, X509_STORE_CTX*);
+
+ /* make sure C++ programs have C linkage for callbacks */
+ void CyaSSL_SetIORecv(SSL_CTX*, CallbackIORecv);
+ void CyaSSL_SetIOSend(SSL_CTX*, CallbackIOSend);
+
+ void CyaSSL_SetIOReadCtx(SSL* ssl, void *ctx);
+ void CyaSSL_SetIOWriteCtx(SSL* ssl, void *ctx);
+#endif /* SSL_TYPES_DEFINED */
+
+
+/* SSL Version */
+typedef struct ProtocolVersion {
+ byte major;
+ byte minor;
+} ProtocolVersion;
+
+
+ProtocolVersion MakeSSLv3(void);
+ProtocolVersion MakeTLSv1(void);
+ProtocolVersion MakeTLSv1_1(void);
+ProtocolVersion MakeTLSv1_2(void);
+
+#ifdef CYASSL_DTLS
+ ProtocolVersion MakeDTLSv1(void);
+#endif
+
+
+enum BIO_TYPE {
+ BIO_BUFFER = 1,
+ BIO_SOCKET = 2,
+ BIO_SSL = 3
+};
+
+
+/* OpenSSL BIO_METHOD type */
+struct BIO_METHOD {
+ byte type; /* method type */
+};
+
+
+/* OpenSSL BIO type */
+struct BIO {
+ byte type; /* method type */
+ byte close; /* close flag */
+ byte eof; /* eof flag */
+ SSL* ssl; /* possible associated ssl */
+ int fd; /* possible file descriptor */
+ BIO* prev; /* previous in chain */
+ BIO* next; /* next in chain */
+};
+
+
+/* OpenSSL method type */
+struct SSL_METHOD {
+ ProtocolVersion version;
+ int side; /* connection side, server or client */
+ int verifyPeer; /* request or send certificate */
+ int verifyNone; /* whether to verify certificate */
+ int failNoCert; /* fail if no certificate */
+ int downgrade; /* whether to downgrade version, default no */
+};
+
+
+/* defautls to client */
+void InitSSL_Method(SSL_METHOD*, ProtocolVersion);
+
+/* for sniffer */
+int DoFinished(SSL* ssl, const byte* input, word32* inOutIdx, int sniff);
+int DoApplicationData(SSL* ssl, byte* input, word32* inOutIdx);
+
+
+/* CyaSSL buffer type */
+typedef struct buffer {
+ word32 length;
+ byte* buffer;
+} buffer;
+
+
+enum {
+ FORCED_FREE = 1,
+ NO_FORCED_FREE = 0
+};
+
+
+/* only use compression extra if using compression */
+#ifdef HAVE_LIBZ
+ #define COMP_EXTRA MAX_COMP_EXTRA
+#else
+ #define COMP_EXTRA 0
+#endif
+
+/* only the sniffer needs space in the buffer for an extra MTU record */
+#ifdef CYASSL_SNIFFER
+ #define MTU_EXTRA MAX_MTU
+#else
+ #define MTU_EXTRA 0
+#endif
+
+/* give user option to use 16K static buffers, sniffer needs them too */
+#if defined(LARGE_STATIC_BUFFERS) || defined(CYASSL_SNIFFER)
+ #define RECORD_SIZE MAX_RECORD_SIZE
+#else
+ #define RECORD_SIZE 128
+#endif
+
+
+/* user option to turn off 16K output option */
+/* if using small static buffers (default) and SSL_write tries to write data
+ larger than the record we have, dynamically get it, unless user says only
+ write in static buffer chuncks */
+#ifndef STATIC_CHUNKS_ONLY
+ #define OUTPUT_RECORD_SIZE MAX_RECORD_SIZE
+#else
+ #define OUTPUT_RECORD_SIZE RECORD_SIZE
+#endif
+
+/* CyaSSL input buffer
+
+ RFC 2246:
+
+ length
+ The length (in bytes) of the following TLSPlaintext.fragment.
+ The length should not exceed 2^14.
+*/
+#define STATIC_BUFFER_LEN RECORD_HEADER_SZ + RECORD_SIZE + COMP_EXTRA + \
+ MTU_EXTRA + MAX_MSG_EXTRA
+
+typedef struct {
+ word32 length; /* total buffer length used */
+ word32 idx; /* idx to part of length already consumed */
+ byte* buffer; /* place holder for static or dynamic buffer */
+ ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN];
+ word32 bufferSize; /* current buffer size */
+ byte dynamicFlag; /* dynamic memory currently in use */
+} bufferStatic;
+
+/* Cipher Suites holder */
+typedef struct Suites {
+ int setSuites; /* user set suites from default */
+ byte suites[MAX_SUITE_SZ];
+ word16 suiteSz; /* suite length in bytes */
+} Suites;
+
+
+void InitSuites(Suites*, ProtocolVersion, byte, byte, byte);
+int SetCipherList(SSL_CTX* ctx, const char* list);
+
+#ifndef PSK_TYPES_DEFINED
+ typedef unsigned int (*psk_client_callback)(SSL*, const char*, char*,
+ unsigned int, unsigned char*, unsigned int);
+ typedef unsigned int (*psk_server_callback)(SSL*, const char*,
+ unsigned char*, unsigned int);
+#endif /* PSK_TYPES_DEFINED */
+
+
+#ifndef CYASSL_USER_IO
+ /* default IO callbacks */
+ int EmbedReceive(char *buf, int sz, void *ctx);
+ int EmbedSend(char *buf, int sz, void *ctx);
+#endif
+
+#ifdef CYASSL_DTLS
+ int IsUDP(void*);
+#endif
+
+
+/* OpenSSL Cipher type just points back to SSL */
+struct SSL_CIPHER {
+ SSL* ssl;
+};
+
+
+/* OpenSSL context type */
+struct SSL_CTX {
+ SSL_METHOD* method;
+ buffer certificate;
+ buffer privateKey;
+ Signer* caList; /* SSL_CTX owns this, SSL will reference */
+ Suites suites;
+ void* heap; /* for user memory overrides */
+ byte verifyPeer;
+ byte verifyNone;
+ byte failNoCert;
+ byte sessionCacheOff;
+ byte sessionCacheFlushOff;
+ byte sendVerify; /* for client side */
+ byte haveDH; /* server DH parms set by user */
+ byte haveNTRU; /* server private NTRU key loaded */
+ byte partialWrite; /* only one msg per write call */
+ byte quietShutdown; /* don't send close notify */
+ CallbackIORecv CBIORecv;
+ CallbackIOSend CBIOSend;
+ VerifyCallback verifyCallback; /* cert verification callback */
+#ifndef NO_PSK
+ byte havePSK; /* psk key set by user */
+ psk_client_callback client_psk_cb; /* client callback */
+ psk_server_callback server_psk_cb; /* server callback */
+ char server_hint[MAX_PSK_ID_LEN];
+#endif /* NO_PSK */
+#ifdef OPENSSL_EXTRA
+ pem_password_cb passwd_cb;
+ void* userdata;
+#endif /* OPENSSL_EXTRA */
+};
+
+
+void InitSSL_Ctx(SSL_CTX*, SSL_METHOD*);
+void FreeSSL_Ctx(SSL_CTX*);
+void SSL_CtxResourceFree(SSL_CTX*);
+
+int DeriveTlsKeys(SSL* ssl);
+int ProcessOldClientHello(SSL* ssl, const byte* input, word32* inOutIdx,
+ word32 inSz, word16 sz);
+
+/* All cipher suite related info */
+typedef struct CipherSpecs {
+ byte bulk_cipher_algorithm;
+ byte cipher_type; /* block or stream */
+ byte mac_algorithm;
+ byte kea; /* key exchange algo */
+ byte sig_algo;
+ byte hash_size;
+ byte pad_size;
+ word16 key_size;
+ word16 iv_size;
+ word16 block_size;
+} CipherSpecs;
+
+
+
+/* Supported Ciphers from page 43 */
+enum BulkCipherAlgorithm {
+ cipher_null,
+ rc4,
+ rc2,
+ des,
+ triple_des, /* leading 3 (3des) not valid identifier */
+ des40,
+ idea,
+ aes,
+ hc128, /* CyaSSL extensions */
+ rabbit
+};
+
+
+/* Supported Message Authentication Codes from page 43 */
+enum MACAlgorithm {
+ no_mac,
+ md5_mac,
+ sha_mac,
+ rmd_mac,
+ sha256_mac
+};
+
+
+/* Supported Key Exchange Protocols */
+enum KeyExchangeAlgorithm {
+ no_kea = 0,
+ rsa_kea,
+ diffie_hellman_kea,
+ fortezza_kea,
+ psk_kea,
+ ntru_kea
+};
+
+
+/* Supported Authentication Schemes */
+enum SignatureAlgorithm {
+ anonymous_sa_algo = 0,
+ rsa_sa_algo,
+ dsa_sa_algo
+};
+
+
+/* Valid client certificate request types from page 27 */
+enum ClientCertificateType {
+ rsa_sign = 1,
+ dss_sign = 2,
+ rsa_fixed_dh = 3,
+ dss_fixed_dh = 4,
+ rsa_ephemeral_dh = 5,
+ dss_ephemeral_dh = 6,
+ fortezza_kea_cert = 20
+};
+
+
+enum CipherType { stream, block };
+
+
+/* keys and secrets */
+typedef struct Keys {
+ byte client_write_MAC_secret[SHA_DIGEST_SIZE]; /* max sizes */
+ byte server_write_MAC_secret[SHA_DIGEST_SIZE];
+ byte client_write_key[AES_256_KEY_SIZE]; /* max sizes */
+ byte server_write_key[AES_256_KEY_SIZE];
+ byte client_write_IV[AES_IV_SIZE]; /* max sizes */
+ byte server_write_IV[AES_IV_SIZE];
+
+ word32 peer_sequence_number;
+ word32 sequence_number;
+
+#ifdef CYASSL_DTLS
+ word32 dtls_sequence_number;
+ word32 dtls_peer_sequence_number;
+ word16 dtls_handshake_number;
+ word16 dtls_epoch;
+ word16 dtls_peer_epoch;
+#endif
+
+ word32 encryptSz; /* last size of encrypted data */
+ byte encryptionOn; /* true after change cipher spec */
+} Keys;
+
+
+/* cipher for now */
+typedef union {
+#ifdef BUILD_ARC4
+ Arc4 arc4;
+#endif
+#ifdef BUILD_DES3
+ Des3 des3;
+#endif
+#ifdef BUILD_AES
+ Aes aes;
+#endif
+#ifdef BUILD_HC128
+ HC128 hc128;
+#endif
+#ifdef BUILD_RABBIT
+ Rabbit rabbit;
+#endif
+} Ciphers;
+
+
+/* hashes type */
+typedef struct Hashes {
+ byte md5[MD5_DIGEST_SIZE];
+ byte sha[SHA_DIGEST_SIZE];
+} Hashes;
+
+
+/* Static x509 buffer */
+typedef struct x509_buffer {
+ int length; /* actual size */
+ byte buffer[MAX_X509_SIZE]; /* max static cert size */
+} x509_buffer;
+
+
+/* CyaSSL X509_CHAIN, for no dynamic memory SESSION_CACHE */
+struct X509_CHAIN {
+ int count; /* total number in chain */
+ x509_buffer certs[MAX_CHAIN_DEPTH]; /* only allow max depth 4 for now */
+};
+
+
+/* openSSL session type */
+struct SSL_SESSION {
+ byte sessionID[ID_LEN];
+ byte masterSecret[SECRET_LEN];
+ word32 bornOn; /* create time in seconds */
+ word32 timeout; /* timeout in seconds */
+#ifdef SESSION_CERTS
+ X509_CHAIN chain; /* peer cert chain, static */
+ ProtocolVersion version;
+ byte cipherSuite;
+#endif
+};
+
+
+SSL_SESSION* GetSession(SSL*, byte*);
+int SetSession(SSL*, SSL_SESSION*);
+
+typedef void (*hmacfp) (SSL*, byte*, const byte*, word32, int, int);
+
+
+/* client connect state for nonblocking restart */
+enum ConnectState {
+ CONNECT_BEGIN = 0,
+ CLIENT_HELLO_SENT,
+ HELLO_AGAIN, /* HELLO_AGAIN s for DTLS case */
+ HELLO_AGAIN_REPLY,
+ FIRST_REPLY_DONE,
+ FIRST_REPLY_FIRST,
+ FIRST_REPLY_SECOND,
+ FIRST_REPLY_THIRD,
+ FIRST_REPLY_FOURTH,
+ FINISHED_DONE,
+ SECOND_REPLY_DONE
+};
+
+
+/* server accpet state for nonblocking restart */
+enum AcceptState {
+ ACCEPT_BEGIN = 0,
+ ACCEPT_CLIENT_HELLO_DONE,
+ HELLO_VERIFY_SENT,
+ ACCEPT_FIRST_REPLY_DONE,
+ SERVER_HELLO_SENT,
+ CERT_SENT,
+ KEY_EXCHANGE_SENT,
+ CERT_REQ_SENT,
+ SERVER_HELLO_DONE,
+ ACCEPT_SECOND_REPLY_DONE,
+ CHANGE_CIPHER_SENT,
+ ACCEPT_FINISHED_DONE,
+ ACCEPT_THIRD_REPLY_DONE
+};
+
+
+typedef struct Buffers {
+ buffer certificate; /* SSL_CTX owns */
+ buffer key; /* SSL_CTX owns */
+ buffer domainName; /* for client check */
+ buffer serverDH_P;
+ buffer serverDH_G;
+ buffer serverDH_Pub;
+ buffer serverDH_Priv;
+ bufferStatic inputBuffer;
+ bufferStatic outputBuffer;
+ buffer clearOutputBuffer;
+ int prevSent; /* previous plain text bytes sent
+ when got WANT_WRITE */
+ int plainSz; /* plain text bytes in buffer to send
+ when got WANT_WRITE */
+} Buffers;
+
+
+typedef struct Options {
+ byte sessionCacheOff;
+ byte sessionCacheFlushOff;
+ byte cipherSuite;
+ byte serverState;
+ byte clientState;
+ byte handShakeState;
+ byte side; /* client or server end */
+ byte verifyPeer;
+ byte verifyNone;
+ byte failNoCert;
+ byte downgrade; /* allow downgrade of versions */
+ byte sendVerify; /* false = 0, true = 1, sendBlank = 2 */
+ byte resuming;
+ byte tls; /* using TLS ? */
+ byte tls1_1; /* using TLSv1.1+ ? */
+ byte dtls; /* using datagrams ? */
+ byte connReset; /* has the peer reset */
+ byte isClosed; /* if we consider conn closed */
+ byte closeNotify; /* we've recieved a close notify */
+ byte sentNotify; /* we've sent a close notify */
+ byte connectState; /* nonblocking resume */
+ byte acceptState; /* nonblocking resume */
+ byte usingCompression; /* are we using compression */
+ byte haveDH; /* server DH parms set by user */
+ byte haveNTRU; /* server NTRU private key loaded */
+ byte havePeerCert; /* do we have peer's cert */
+ byte usingPSK_cipher; /* whether we're using psk as cipher */
+ byte sendAlertState; /* nonblocking resume */
+ byte processReply; /* nonblocking resume */
+ byte partialWrite; /* only one msg per write call */
+ byte quietShutdown; /* don't send close notify */
+#ifndef NO_PSK
+ byte havePSK; /* psk key set by user */
+ psk_client_callback client_psk_cb;
+ psk_server_callback server_psk_cb;
+#endif /* NO_PSK */
+} Options;
+
+
+typedef struct Arrays {
+ byte clientRandom[RAN_LEN];
+ byte serverRandom[RAN_LEN];
+ byte sessionID[ID_LEN];
+ byte preMasterSecret[ENCRYPT_LEN];
+ byte masterSecret[SECRET_LEN];
+#ifdef CYASSL_DTLS
+ byte cookie[MAX_COOKIE_LEN];
+#endif
+#ifndef NO_PSK
+ char client_identity[MAX_PSK_ID_LEN];
+ char server_hint[MAX_PSK_ID_LEN];
+ byte psk_key[MAX_PSK_KEY_LEN];
+ word32 psk_keySz; /* acutal size */
+#endif
+ word32 preMasterSz; /* differs for DH, actual size */
+} Arrays;
+
+
+#undef X509_NAME
+
+struct X509_NAME {
+ char name[ASN_NAME_MAX];
+ int sz;
+};
+
+
+struct X509 {
+ X509_NAME issuer;
+ X509_NAME subject;
+};
+
+
+/* record layer header for PlainText, Compressed, and CipherText */
+typedef struct RecordLayerHeader {
+ byte type;
+ ProtocolVersion version;
+ byte length[2];
+} RecordLayerHeader;
+
+
+/* record layer header for DTLS PlainText, Compressed, and CipherText */
+typedef struct DtlsRecordLayerHeader {
+ byte type;
+ ProtocolVersion version;
+ byte epoch[2]; /* increment on cipher state change */
+ byte sequence_number[6]; /* per record */
+ byte length[2];
+} DtlsRecordLayerHeader;
+
+
+/* OpenSSL ssl type */
+struct SSL {
+ SSL_CTX* ctx;
+ int error;
+ ProtocolVersion version; /* negotiated version */
+ ProtocolVersion chVersion; /* client hello version */
+ Suites suites;
+ Ciphers encrypt;
+ Ciphers decrypt;
+ CipherSpecs specs;
+ Keys keys;
+ int rfd; /* read file descriptor */
+ int wfd; /* write file descriptor */
+ BIO* biord; /* socket bio read to free/close */
+ BIO* biowr; /* socket bio write to free/close */
+ void* IOCB_ReadCtx;
+ void* IOCB_WriteCtx;
+ RNG rng;
+ Md5 hashMd5; /* md5 hash of handshake msgs */
+ Sha hashSha; /* sha hash of handshake msgs */
+ Hashes verifyHashes;
+ Hashes certHashes; /* for cert verify */
+ Signer* caList; /* SSL_CTX owns */
+ Buffers buffers;
+ Options options;
+ Arrays arrays;
+ SSL_SESSION session;
+ RsaKey peerRsaKey;
+ byte peerRsaKeyPresent;
+#ifdef HAVE_NTRU
+ word16 peerNtruKeyLen;
+ byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ];
+ byte peerNtruKeyPresent;
+#endif
+ hmacfp hmac;
+ void* heap; /* for user overrides */
+ RecordLayerHeader curRL;
+ word16 curSize;
+ SSL_CIPHER cipher;
+#ifdef HAVE_LIBZ
+ z_stream c_stream; /* compression stream */
+ z_stream d_stream; /* decompression stream */
+ byte didStreamInit; /* for stream init and end */
+#endif
+#ifdef CYASSL_CALLBACKS
+ HandShakeInfo handShakeInfo; /* info saved during handshake */
+ TimeoutInfo timeoutInfo; /* info saved during handshake */
+ byte hsInfoOn; /* track handshake info */
+ byte toInfoOn; /* track timeout info */
+#endif
+#ifdef OPENSSL_EXTRA
+ X509 peerCert; /* X509 peer cert */
+#endif
+};
+
+
+int InitSSL(SSL*, SSL_CTX*);
+void FreeSSL(SSL*);
+void SSL_ResourceFree(SSL*);
+
+
+enum {
+ IV_SZ = 32, /* max iv sz */
+ NAME_SZ = 80, /* max one line */
+};
+
+
+typedef struct EncryptedInfo {
+ char name[NAME_SZ];
+ byte iv[IV_SZ];
+ word32 ivSz;
+ byte set;
+} EncryptedInfo;
+
+
+#ifdef CYASSL_CALLBACKS
+ void InitHandShakeInfo(HandShakeInfo*);
+ void FinishHandShakeInfo(HandShakeInfo*, const SSL*);
+ void AddPacketName(const char*, HandShakeInfo*);
+
+ void InitTimeoutInfo(TimeoutInfo*);
+ void FreeTimeoutInfo(TimeoutInfo*, void*);
+ void AddPacketInfo(const char*, TimeoutInfo*, const byte*, int, void*);
+ void AddLateName(const char*, TimeoutInfo*);
+ void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info);
+#endif
+
+
+/* Record Layer Header identifier from page 12 */
+enum ContentType {
+ no_type = 0,
+ change_cipher_spec = 20,
+ alert = 21,
+ handshake = 22,
+ application_data = 23
+};
+
+
+/* handshake header, same for each message type, pgs 20/21 */
+typedef struct HandShakeHeader {
+ byte type;
+ word24 length;
+} HandShakeHeader;
+
+
+/* DTLS handshake header, same for each message type */
+typedef struct DtlsHandShakeHeader {
+ byte type;
+ word24 length;
+ byte message_seq[2]; /* start at 0, restransmit gets same # */
+ word24 fragment_offset; /* bytes in previous fragments */
+ word24 fragment_length; /* length of this fragment */
+} DtlsHandShakeHeader;
+
+
+enum HandShakeType {
+ no_shake = -1,
+ hello_request = 0,
+ client_hello = 1,
+ server_hello = 2,
+ hello_verify_request = 3, /* DTLS addition */
+ certificate = 11,
+ server_key_exchange = 12,
+ certificate_request = 13,
+ server_hello_done = 14,
+ certificate_verify = 15,
+ client_key_exchange = 16,
+ finished = 20
+};
+
+
+/* Valid Alert types from page 16/17 */
+enum AlertDescription {
+ close_notify = 0,
+ unexpected_message = 10,
+ bad_record_mac = 20,
+ decompression_failure = 30,
+ handshake_failure = 40,
+ no_certificate = 41,
+ bad_certificate = 42,
+ unsupported_certificate = 43,
+ certificate_revoked = 44,
+ certificate_expired = 45,
+ certificate_unknown = 46,
+ illegal_parameter = 47,
+ decrypt_error = 51
+};
+
+
+/* I/O Callback default errors */
+enum IOerrors {
+ IO_ERR_GENERAL = -1, /* general unexpected err, not in below group */
+ IO_ERR_WANT_READ = -2, /* need to call read again */
+ IO_ERR_WANT_WRITE = -2, /* need to call write again */
+ IO_ERR_CONN_RST = -3, /* connection reset */
+ IO_ERR_ISR = -4, /* interrupt */
+ IO_ERR_CONN_CLOSE = -5 /* connection closed or epipe */
+};
+
+
+enum AlertLevel {
+ alert_warning = 1,
+ alert_fatal = 2
+};
+
+
+static const byte client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 };
+static const byte server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 };
+
+static const byte tls_client[FINISHED_LABEL_SZ + 1] = "client finished";
+static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
+
+
+/* internal functions */
+int SendChangeCipher(SSL*);
+int SendData(SSL*, const void*, int);
+int SendCertificate(SSL*);
+int SendCertificateRequest(SSL*);
+int SendServerKeyExchange(SSL*);
+int SendBuffered(SSL*);
+int ReceiveData(SSL*, byte*, int);
+int SendFinished(SSL*);
+int SendAlert(SSL*, int, int);
+int ProcessReply(SSL*);
+
+int SetCipherSpecs(SSL*);
+int MakeMasterSecret(SSL*);
+
+int AddSession(SSL*);
+int DeriveKeys(SSL* ssl);
+int StoreKeys(SSL* ssl, const byte* keyData);
+
+int IsTLS(const SSL* ssl);
+int IsAtLeastTLSv1_2(const SSL* ssl);
+
+void ShrinkInputBuffer(SSL* ssl, int forcedFree);
+void ShrinkOutputBuffer(SSL* ssl);
+
+#ifndef NO_CYASSL_CLIENT
+ int SendClientHello(SSL*);
+ int SendClientKeyExchange(SSL*);
+ int SendCertificateVerify(SSL*);
+#endif /* NO_CYASSL_CLIENT */
+
+#ifndef NO_CYASSL_SERVER
+ int SendServerHello(SSL*);
+ int SendServerHelloDone(SSL*);
+ #ifdef CYASSL_DTLS
+ int SendHelloVerifyRequest(SSL*);
+ #endif
+#endif /* NO_CYASSL_SERVER */
+
+
+#ifndef NO_TLS
+
+
+#endif /* NO_TLS */
+
+
+
+typedef double timer_d;
+
+timer_d Timer(void);
+word32 LowResTimer(void);
+
+
+#ifdef SINGLE_THREADED
+ typedef int CyaSSL_Mutex;
+#else /* MULTI_THREADED */
+ #ifdef USE_WINDOWS_API
+ typedef CRITICAL_SECTION CyaSSL_Mutex;
+ #elif defined(CYASSL_PTHREADS)
+ typedef pthread_mutex_t CyaSSL_Mutex;
+ #elif defined(THREADX)
+ typedef TX_MUTEX CyaSSL_Mutex;
+ #elif defined(MICRIUM)
+ typedef OS_MUTEX CyaSSL_Mutex;
+ #else
+ #error Need a mutex type in multithreaded mode
+ #endif /* USE_WINDOWS_API */
+#endif /* SINGLE_THREADED */
+
+int InitMutex(CyaSSL_Mutex*);
+int FreeMutex(CyaSSL_Mutex*);
+int LockMutex(CyaSSL_Mutex*);
+int UnLockMutex(CyaSSL_Mutex*);
+
+
+#ifdef DEBUG_CYASSL
+
+ void CYASSL_ENTER(const char* msg);
+ void CYASSL_LEAVE(const char* msg, int ret);
+
+ void CYASSL_ERROR(int);
+ void CYASSL_MSG(const char* msg);
+
+#else /* DEBUG_CYASSL */
+
+ #define CYASSL_ENTER(m)
+ #define CYASSL_LEAVE(m, r)
+
+ #define CYASSL_ERROR(e)
+ #define CYASSL_MSG(m)
+
+#endif /* DEBUG_CYASSL */
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CyaSSL_INT_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cyassl_io.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,192 @@
+/* cyassl_io.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifdef _WIN32_WCE
+ /* On WinCE winsock2.h must be included before windows.h for socket stuff */
+ #include <winsock2.h>
+#endif
+
+#include "cyassl_int.h"
+
+/* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove
+ automatic setting of defualt I/O functions EmbedSend() and EmbedReceive()
+ but they'll still nedd SetCallback xxx() at end of file
+*/
+#ifndef CYASSL_USER_IO
+
+#ifdef HAVE_LIBZ
+ #include "zlib.h"
+#endif
+
+#ifndef USE_WINDOWS_API
+ #include <sys/types.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #if !(defined(DEVKITPRO) || defined(THREADX))
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #include <sys/ioctl.h>
+ #endif
+ #ifdef THREADX
+ #include <socket.h>
+ #endif
+#endif /* USE_WINDOWS_API */
+
+#ifdef __sun
+ #include <sys/filio.h>
+#endif
+
+#ifdef USE_WINDOWS_API
+ /* no epipe yet */
+ #ifndef WSAEPIPE
+ #define WSAEPIPE -12345
+ #endif
+ #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
+ #define SOCKET_EAGAIN WSAEWOULDBLOCK
+ #define SOCKET_ECONNRESET WSAECONNRESET
+ #define SOCKET_EINTR WSAEINTR
+ #define SOCKET_EPIPE WSAEPIPE
+#else
+ #define SOCKET_EWOULDBLOCK EWOULDBLOCK
+ #define SOCKET_EAGAIN EAGAIN
+ #define SOCKET_ECONNRESET ECONNRESET
+ #define SOCKET_EINTR EINTR
+ #define SOCKET_EPIPE EPIPE
+#endif /* USE_WINDOWS_API */
+
+
+#ifdef DEVKITPRO
+ /* from network.h */
+ int net_send(int, const void*, int, unsigned int);
+ int net_recv(int, void*, int, unsigned int);
+ #define SEND_FUNCTION net_send
+ #define RECV_FUNCTION net_recv
+#else
+ #define SEND_FUNCTION send
+ #define RECV_FUNCTION recv
+#endif
+
+
+static INLINE int LastError(void)
+{
+#ifdef USE_WINDOWS_API
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+/* The receive embedded callback
+ * return : nb bytes read, or error
+ */
+int EmbedReceive(char *buf, int sz, void *ctx)
+{
+ int recvd;
+ int err;
+ int socket = *(int*)ctx;
+
+ recvd = RECV_FUNCTION(socket, (char *)buf, sz, 0);
+
+ if (recvd == -1) {
+ err = LastError();
+ if (err == SOCKET_EWOULDBLOCK ||
+ err == SOCKET_EAGAIN)
+ return IO_ERR_WANT_READ;
+
+ else if (err == SOCKET_ECONNRESET)
+ return IO_ERR_CONN_RST;
+
+ else if (err == SOCKET_EINTR)
+ return IO_ERR_ISR;
+
+ else
+ return IO_ERR_GENERAL;
+ }
+ else if (recvd == 0)
+ return IO_ERR_CONN_CLOSE;
+
+ return recvd;
+}
+
+/* The send embedded callback
+ * return : nb bytes sent, or error
+ */
+int EmbedSend(char *buf, int sz, void *ctx)
+{
+ int socket = *(int*)ctx;
+ int sent;
+ int len = sz;
+
+ sent = SEND_FUNCTION(socket, &buf[sz - len], len, 0);
+
+ if (sent == -1) {
+ if (LastError() == SOCKET_EWOULDBLOCK ||
+ LastError() == SOCKET_EAGAIN)
+ return IO_ERR_WANT_WRITE;
+
+ else if (LastError() == SOCKET_ECONNRESET)
+ return IO_ERR_CONN_RST;
+
+ else if (LastError() == SOCKET_EINTR)
+ return IO_ERR_ISR;
+
+ else if (LastError() == SOCKET_EPIPE)
+ return IO_ERR_CONN_CLOSE;
+
+ else
+ return IO_ERR_GENERAL;
+ }
+
+ return sent;
+}
+
+
+#endif /* CYASSL_USER_IO */
+
+
+
+void CyaSSL_SetIORecv(SSL_CTX *ctx, CallbackIORecv CBIORecv)
+{
+ ctx->CBIORecv = CBIORecv;
+}
+
+
+void CyaSSL_SetIOSend(SSL_CTX *ctx, CallbackIOSend CBIOSend)
+{
+ ctx->CBIOSend = CBIOSend;
+}
+
+
+void CyaSSL_SetIOReadCtx(SSL* ssl, void *rctx)
+{
+ ssl->IOCB_ReadCtx = rctx;
+}
+
+
+void CyaSSL_SetIOWriteCtx(SSL* ssl, void *wctx)
+{
+ ssl->IOCB_WriteCtx = wctx;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/des3.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,493 @@
+/* des3.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_DES3
+
+#include "des3.h"
+#ifdef NO_INLINE
+ #include "misc.h"
+#else
+ #include "misc.c"
+#endif
+
+
+/* permuted choice table (key) */
+static const byte pc1[] = {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+};
+
+/* number left rotations of pc1 */
+static const byte totrot[] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
+};
+
+/* permuted choice key (table) */
+static const byte pc2[] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+/* End of DES-defined tables */
+
+/* bit 0 is left-most in byte */
+static const int bytebit[] = {
+ 0200,0100,040,020,010,04,02,01
+};
+
+const word32 Spbox[8][64] = {
+{
+0x01010400,0x00000000,0x00010000,0x01010404,
+0x01010004,0x00010404,0x00000004,0x00010000,
+0x00000400,0x01010400,0x01010404,0x00000400,
+0x01000404,0x01010004,0x01000000,0x00000004,
+0x00000404,0x01000400,0x01000400,0x00010400,
+0x00010400,0x01010000,0x01010000,0x01000404,
+0x00010004,0x01000004,0x01000004,0x00010004,
+0x00000000,0x00000404,0x00010404,0x01000000,
+0x00010000,0x01010404,0x00000004,0x01010000,
+0x01010400,0x01000000,0x01000000,0x00000400,
+0x01010004,0x00010000,0x00010400,0x01000004,
+0x00000400,0x00000004,0x01000404,0x00010404,
+0x01010404,0x00010004,0x01010000,0x01000404,
+0x01000004,0x00000404,0x00010404,0x01010400,
+0x00000404,0x01000400,0x01000400,0x00000000,
+0x00010004,0x00010400,0x00000000,0x01010004},
+{
+0x80108020,0x80008000,0x00008000,0x00108020,
+0x00100000,0x00000020,0x80100020,0x80008020,
+0x80000020,0x80108020,0x80108000,0x80000000,
+0x80008000,0x00100000,0x00000020,0x80100020,
+0x00108000,0x00100020,0x80008020,0x00000000,
+0x80000000,0x00008000,0x00108020,0x80100000,
+0x00100020,0x80000020,0x00000000,0x00108000,
+0x00008020,0x80108000,0x80100000,0x00008020,
+0x00000000,0x00108020,0x80100020,0x00100000,
+0x80008020,0x80100000,0x80108000,0x00008000,
+0x80100000,0x80008000,0x00000020,0x80108020,
+0x00108020,0x00000020,0x00008000,0x80000000,
+0x00008020,0x80108000,0x00100000,0x80000020,
+0x00100020,0x80008020,0x80000020,0x00100020,
+0x00108000,0x00000000,0x80008000,0x00008020,
+0x80000000,0x80100020,0x80108020,0x00108000},
+{
+0x00000208,0x08020200,0x00000000,0x08020008,
+0x08000200,0x00000000,0x00020208,0x08000200,
+0x00020008,0x08000008,0x08000008,0x00020000,
+0x08020208,0x00020008,0x08020000,0x00000208,
+0x08000000,0x00000008,0x08020200,0x00000200,
+0x00020200,0x08020000,0x08020008,0x00020208,
+0x08000208,0x00020200,0x00020000,0x08000208,
+0x00000008,0x08020208,0x00000200,0x08000000,
+0x08020200,0x08000000,0x00020008,0x00000208,
+0x00020000,0x08020200,0x08000200,0x00000000,
+0x00000200,0x00020008,0x08020208,0x08000200,
+0x08000008,0x00000200,0x00000000,0x08020008,
+0x08000208,0x00020000,0x08000000,0x08020208,
+0x00000008,0x00020208,0x00020200,0x08000008,
+0x08020000,0x08000208,0x00000208,0x08020000,
+0x00020208,0x00000008,0x08020008,0x00020200},
+{
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802080,0x00800081,0x00800001,0x00002001,
+0x00000000,0x00802000,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00800080,0x00800001,
+0x00000001,0x00002000,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002001,0x00002080,
+0x00800081,0x00000001,0x00002080,0x00800080,
+0x00002000,0x00802080,0x00802081,0x00000081,
+0x00800080,0x00800001,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00000000,0x00802000,
+0x00002080,0x00800080,0x00800081,0x00000001,
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802081,0x00000081,0x00000001,0x00002000,
+0x00800001,0x00002001,0x00802080,0x00800081,
+0x00002001,0x00002080,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002000,0x00802080},
+{
+0x00000100,0x02080100,0x02080000,0x42000100,
+0x00080000,0x00000100,0x40000000,0x02080000,
+0x40080100,0x00080000,0x02000100,0x40080100,
+0x42000100,0x42080000,0x00080100,0x40000000,
+0x02000000,0x40080000,0x40080000,0x00000000,
+0x40000100,0x42080100,0x42080100,0x02000100,
+0x42080000,0x40000100,0x00000000,0x42000000,
+0x02080100,0x02000000,0x42000000,0x00080100,
+0x00080000,0x42000100,0x00000100,0x02000000,
+0x40000000,0x02080000,0x42000100,0x40080100,
+0x02000100,0x40000000,0x42080000,0x02080100,
+0x40080100,0x00000100,0x02000000,0x42080000,
+0x42080100,0x00080100,0x42000000,0x42080100,
+0x02080000,0x00000000,0x40080000,0x42000000,
+0x00080100,0x02000100,0x40000100,0x00080000,
+0x00000000,0x40080000,0x02080100,0x40000100},
+{
+0x20000010,0x20400000,0x00004000,0x20404010,
+0x20400000,0x00000010,0x20404010,0x00400000,
+0x20004000,0x00404010,0x00400000,0x20000010,
+0x00400010,0x20004000,0x20000000,0x00004010,
+0x00000000,0x00400010,0x20004010,0x00004000,
+0x00404000,0x20004010,0x00000010,0x20400010,
+0x20400010,0x00000000,0x00404010,0x20404000,
+0x00004010,0x00404000,0x20404000,0x20000000,
+0x20004000,0x00000010,0x20400010,0x00404000,
+0x20404010,0x00400000,0x00004010,0x20000010,
+0x00400000,0x20004000,0x20000000,0x00004010,
+0x20000010,0x20404010,0x00404000,0x20400000,
+0x00404010,0x20404000,0x00000000,0x20400010,
+0x00000010,0x00004000,0x20400000,0x00404010,
+0x00004000,0x00400010,0x20004010,0x00000000,
+0x20404000,0x20000000,0x00400010,0x20004010},
+{
+0x00200000,0x04200002,0x04000802,0x00000000,
+0x00000800,0x04000802,0x00200802,0x04200800,
+0x04200802,0x00200000,0x00000000,0x04000002,
+0x00000002,0x04000000,0x04200002,0x00000802,
+0x04000800,0x00200802,0x00200002,0x04000800,
+0x04000002,0x04200000,0x04200800,0x00200002,
+0x04200000,0x00000800,0x00000802,0x04200802,
+0x00200800,0x00000002,0x04000000,0x00200800,
+0x04000000,0x00200800,0x00200000,0x04000802,
+0x04000802,0x04200002,0x04200002,0x00000002,
+0x00200002,0x04000000,0x04000800,0x00200000,
+0x04200800,0x00000802,0x00200802,0x04200800,
+0x00000802,0x04000002,0x04200802,0x04200000,
+0x00200800,0x00000000,0x00000002,0x04200802,
+0x00000000,0x00200802,0x04200000,0x00000800,
+0x04000002,0x04000800,0x00000800,0x00200002},
+{
+0x10001040,0x00001000,0x00040000,0x10041040,
+0x10000000,0x10001040,0x00000040,0x10000000,
+0x00040040,0x10040000,0x10041040,0x00041000,
+0x10041000,0x00041040,0x00001000,0x00000040,
+0x10040000,0x10000040,0x10001000,0x00001040,
+0x00041000,0x00040040,0x10040040,0x10041000,
+0x00001040,0x00000000,0x00000000,0x10040040,
+0x10000040,0x10001000,0x00041040,0x00040000,
+0x00041040,0x00040000,0x10041000,0x00001000,
+0x00000040,0x10040040,0x00001000,0x00041040,
+0x10001000,0x00000040,0x10000040,0x10040000,
+0x10040040,0x10000000,0x00040000,0x10001040,
+0x00000000,0x10041040,0x00040040,0x10000040,
+0x10040000,0x10001000,0x10001040,0x00000000,
+0x10041040,0x00041000,0x00041000,0x00001040,
+0x00001040,0x00040040,0x10000000,0x10041000}
+};
+
+
+static INLINE void IPERM(word32* left, word32* right)
+{
+ word32 work;
+
+ *right = rotlFixed(*right, 4U);
+ work = (*left ^ *right) & 0xf0f0f0f0;
+ *left ^= work;
+
+ *right = rotrFixed(*right^work, 20U);
+ work = (*left ^ *right) & 0xffff0000;
+ *left ^= work;
+
+ *right = rotrFixed(*right^work, 18U);
+ work = (*left ^ *right) & 0x33333333;
+ *left ^= work;
+
+ *right = rotrFixed(*right^work, 6U);
+ work = (*left ^ *right) & 0x00ff00ff;
+ *left ^= work;
+
+ *right = rotlFixed(*right^work, 9U);
+ work = (*left ^ *right) & 0xaaaaaaaa;
+ *left = rotlFixed(*left^work, 1U);
+ *right ^= work;
+}
+
+
+static INLINE void FPERM(word32* left, word32* right)
+{
+ word32 work;
+
+ *right = rotrFixed(*right, 1U);
+ work = (*left ^ *right) & 0xaaaaaaaa;
+ *right ^= work;
+
+ *left = rotrFixed(*left^work, 9U);
+ work = (*left ^ *right) & 0x00ff00ff;
+ *right ^= work;
+
+ *left = rotlFixed(*left^work, 6U);
+ work = (*left ^ *right) & 0x33333333;
+ *right ^= work;
+
+ *left = rotlFixed(*left^work, 18U);
+ work = (*left ^ *right) & 0xffff0000;
+ *right ^= work;
+
+ *left = rotlFixed(*left^work, 20U);
+ work = (*left ^ *right) & 0xf0f0f0f0;
+ *right ^= work;
+
+ *left = rotrFixed(*left^work, 4U);
+}
+
+
+static void DesSetKey(const byte* key, int dir, word32* out)
+{
+ byte buffer[56+56+8];
+ byte *const pc1m = buffer; /* place to modify pc1 into */
+ byte *const pcr = pc1m + 56; /* place to rotate pc1 into */
+ byte *const ks = pcr + 56;
+ register int i,j,l;
+ int m;
+
+ for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */
+ l = pc1[j] - 1; /* integer bit location */
+ m = l & 07; /* find bit */
+ pc1m[j] = (key[l >> 3] & /* find which key byte l is in */
+ bytebit[m]) /* and which bit of that byte */
+ ? 1 : 0; /* and store 1-bit result */
+ }
+ for (i = 0; i < 16; i++) { /* key chunk for each iteration */
+ XMEMSET(ks, 0, 8); /* Clear key schedule */
+ for (j = 0; j < 56; j++) /* rotate pc1 the right amount */
+ pcr[j] = pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l: l-28];
+ /* rotate left and right halves independently */
+ for (j = 0; j < 48; j++){ /* select bits individually */
+ /* check bit that goes to ks[j] */
+ if (pcr[pc2[j] - 1]){
+ /* mask it in if it's there */
+ l= j % 6;
+ ks[j/6] |= bytebit[l] >> 2;
+ }
+ }
+ /* Now convert to odd/even interleaved form for use in F */
+ out[2*i] = ((word32)ks[0] << 24)
+ | ((word32)ks[2] << 16)
+ | ((word32)ks[4] << 8)
+ | ((word32)ks[6]);
+ out[2*i + 1] = ((word32)ks[1] << 24)
+ | ((word32)ks[3] << 16)
+ | ((word32)ks[5] << 8)
+ | ((word32)ks[7]);
+ }
+
+ /* reverse key schedule order */
+ if (dir == DES_DECRYPTION)
+ for (i = 0; i < 16; i += 2) {
+ word32 swap = out[i];
+ out[i] = out[DES_KS_SIZE - 2 - i];
+ out[DES_KS_SIZE - 2 - i] = swap;
+
+ swap = out[i + 1];
+ out[i + 1] = out[DES_KS_SIZE - 1 - i];
+ out[DES_KS_SIZE - 1 - i] = swap;
+ }
+
+}
+
+
+static INLINE int Reverse(int dir)
+{
+ return !dir;
+}
+
+
+void Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
+{
+ DesSetKey(key, dir, des->key);
+
+ XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
+}
+
+
+void Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
+{
+ DesSetKey(key + (dir == DES_ENCRYPTION ? 0 : 16), dir, des->key[0]);
+ DesSetKey(key + 8, Reverse(dir), des->key[1]);
+ DesSetKey(key + (dir == DES_DECRYPTION ? 0 : 16), dir, des->key[2]);
+
+ XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
+}
+
+
+void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr)
+{
+ word32 l = *lIn, r = *rIn, i;
+
+ for (i=0; i<8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ *lIn = l; *rIn = r;
+}
+
+
+static void DesProcessBlock(Des* des, const byte* in, byte* out)
+{
+ word32 l, r;
+
+ XMEMCPY(&l, in, sizeof(l));
+ XMEMCPY(&r, in + sizeof(l), sizeof(r));
+ #ifdef LITTLE_ENDIAN_ORDER
+ l = ByteReverseWord32(l);
+ r = ByteReverseWord32(r);
+ #endif
+ IPERM(&l,&r);
+
+ DesRawProcessBlock(&l, &r, des->key);
+
+ FPERM(&l,&r);
+ #ifdef LITTLE_ENDIAN_ORDER
+ l = ByteReverseWord32(l);
+ r = ByteReverseWord32(r);
+ #endif
+ XMEMCPY(out, &r, sizeof(r));
+ XMEMCPY(out + sizeof(r), &l, sizeof(l));
+}
+
+
+static void Des3ProcessBlock(Des3* des, const byte* in, byte* out)
+{
+ word32 l, r;
+
+ XMEMCPY(&l, in, sizeof(l));
+ XMEMCPY(&r, in + sizeof(l), sizeof(r));
+ #ifdef LITTLE_ENDIAN_ORDER
+ l = ByteReverseWord32(l);
+ r = ByteReverseWord32(r);
+ #endif
+ IPERM(&l,&r);
+
+ DesRawProcessBlock(&l, &r, des->key[0]);
+ DesRawProcessBlock(&r, &l, des->key[1]);
+ DesRawProcessBlock(&l, &r, des->key[2]);
+
+ FPERM(&l,&r);
+ #ifdef LITTLE_ENDIAN_ORDER
+ l = ByteReverseWord32(l);
+ r = ByteReverseWord32(r);
+ #endif
+ XMEMCPY(out, &r, sizeof(r));
+ XMEMCPY(out + sizeof(r), &l, sizeof(l));
+}
+
+
+void Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / DES_BLOCK_SIZE;
+
+ while (blocks--) {
+ xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
+ DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
+ XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
+
+ out += DES_BLOCK_SIZE;
+ in += DES_BLOCK_SIZE;
+ }
+}
+
+
+void Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / DES_BLOCK_SIZE;
+ byte hold[16];
+
+ while (blocks--) {
+ XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
+ DesProcessBlock(des, (byte*)des->tmp, out);
+ xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
+
+ XMEMCPY(hold, des->reg, DES_BLOCK_SIZE);
+ XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
+ XMEMCPY(des->tmp, hold, DES_BLOCK_SIZE);
+
+ out += DES_BLOCK_SIZE;
+ in += DES_BLOCK_SIZE;
+ }
+}
+
+
+void Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / DES_BLOCK_SIZE;
+
+ while (blocks--) {
+ xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
+ Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
+ XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
+
+ out += DES_BLOCK_SIZE;
+ in += DES_BLOCK_SIZE;
+ }
+}
+
+
+void Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / DES_BLOCK_SIZE;
+
+ while (blocks--) {
+ XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
+ Des3ProcessBlock(des, (byte*)des->tmp, out);
+ xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
+ XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
+
+ out += DES_BLOCK_SIZE;
+ in += DES_BLOCK_SIZE;
+ }
+}
+
+
+#endif /* NO_DES3 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/des3.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,75 @@
+/* des3.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef NO_DES3
+
+#ifndef CTAO_CRYPT_DES3_H
+#define CTAO_CRYPT_DES3_H
+
+
+#include "types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+enum {
+ DES_BLOCK_SIZE = 8,
+ DES_KS_SIZE = 32,
+
+ DES_ENCRYPTION = 0,
+ DES_DECRYPTION = 1,
+};
+
+
+/* DES encryption and decryption */
+typedef struct Des {
+ word32 key[DES_KS_SIZE];
+ word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
+ word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */
+} Des;
+
+
+/* DES3 encryption and decryption */
+typedef struct Des3 {
+ word32 key[3][DES_KS_SIZE];
+ word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */
+ word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */
+} Des3;
+
+
+void Des_SetKey(Des* des, const byte* key, const byte* iv, int dir);
+void Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz);
+void Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz);
+
+void Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir);
+void Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz);
+void Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* NO_DES3 */
+#endif /* CTAO_CRYPT_DES3_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/error.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,100 @@
+/* error.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_ERROR_H
+#define CTAO_CRYPT_ERROR_H
+
+#include "types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/* error codes */
+enum {
+ MAX_ERROR_SZ = 80, /* max size of error string */
+ MAX_CODE_E = -100, /* errors -101 - -199 */
+ OPEN_RAN_E = -101, /* opening random device error */
+ READ_RAN_E = -102, /* reading random device error */
+ WINCRYPT_E = -103, /* windows crypt init error */
+ CRYPTGEN_E = -104, /* windows crypt generation error */
+ RAN_BLOCK_E = -105, /* reading random device would block */
+
+ MP_INIT_E = -110, /* mp_init error state */
+ MP_READ_E = -111, /* mp_read error state */
+ MP_EXPTMOD_E = -112, /* mp_exptmod error state */
+ MP_TO_E = -113, /* mp_to_xxx error state, can't convert */
+ MP_SUB_E = -114, /* mp_sub error state, can't subtract */
+ MP_ADD_E = -115, /* mp_add error state, can't add */
+ MP_MUL_E = -116, /* mp_mul error state, can't multiply */
+ MP_MULMOD_E = -117, /* mp_mulmod error state, can't multiply mod */
+ MP_MOD_E = -118, /* mp_mod error state, can't mod */
+ MP_INVMOD_E = -119, /* mp_invmod error state, can't inv mod */
+ MP_CMP_E = -120, /* mp_cmp error state */
+
+ MEMORY_E = -125, /* out of memory error */
+
+ RSA_WRONG_TYPE_E = -130, /* RSA wrong block type for RSA function */
+ RSA_BUFFER_E = -131, /* RSA buffer error, output too small or
+ input too large */
+ BUFFER_E = -132, /* output buffer too small or input too large */
+ ALGO_ID_E = -133, /* setting algo id error */
+ PUBLIC_KEY_E = -134, /* setting public key error */
+ DATE_E = -135, /* setting date validity error */
+ SUBJECT_E = -136, /* setting subject name error */
+ ISSUER_E = -137, /* setting issuer name error */
+
+ ASN_PARSE_E = -140, /* ASN parsing error, invalid input */
+ ASN_VERSION_E = -141, /* ASN version error, invalid number */
+ ASN_GETINT_E = -142, /* ASN get big int error, invalid data */
+ ASN_RSA_KEY_E = -143, /* ASN key init error, invalid input */
+ ASN_OBJECT_ID_E = -144, /* ASN object id error, invalid id */
+ ASN_TAG_NULL_E = -145, /* ASN tag error, not null */
+ ASN_EXPECT_0_E = -146, /* ASN expect error, not zero */
+ ASN_BITSTR_E = -147, /* ASN bit string error, wrong id */
+ ASN_UNKNOWN_OID_E = -148, /* ASN oid error, unknown sum id */
+ ASN_DATE_SZ_E = -149, /* ASN date error, bad size */
+ ASN_BEFORE_DATE_E = -150, /* ASN date error, current date before */
+ ASN_AFTER_DATE_E = -151, /* ASN date error, current date after */
+ ASN_SIG_OID_E = -152, /* ASN signature error, mismatched oid */
+ ASN_TIME_E = -153, /* ASN time error, unkown time type */
+ ASN_INPUT_E = -154, /* ASN input error, not enough data */
+ ASN_SIG_CONFIRM_E = -155, /* ASN sig error, confirm failure */
+ ASN_SIG_HASH_E = -156, /* ASN sig error, unsupported hash type */
+ ASN_SIG_KEY_E = -157, /* ASN sig error, unsupported key type */
+ ASN_DH_KEY_E = -158, /* ASN key init error, invalid input */
+ ASN_NTRU_KEY_E = -159, /* ASN ntru key decode error, invalid input */
+ MIN_CODE_E = -200 /* errors -101 - -199 */
+};
+
+
+void CTaoCryptErrorString(int error, char* buffer);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_ERROR_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hc128.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,57 @@
+/* hc128.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_HC128
+
+#ifndef CTAO_CRYPT_HC128_H
+#define CTAO_CRYPT_HC128_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/* HC-128 stream cipher */
+typedef struct HC128 {
+ word32 T[1024]; /* P[i] = T[i]; Q[i] = T[1024 + i ]; */
+ word32 X[16];
+ word32 Y[16];
+ word32 counter1024; /* counter1024 = i mod 1024 at the ith step */
+ word32 key[8];
+ word32 iv[8];
+} HC128;
+
+
+void Hc128_Process(HC128*, byte*, const byte*, word32);
+void Hc128_SetKey(HC128*, const byte* key, const byte* iv);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_HC128_H */
+
+#endif /* NO_HC128 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hmac.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,158 @@
+/* hmac.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_HMAC
+
+#include "ctc_hmac.h"
+
+
+
+static int InitHmac(Hmac* hmac, int type)
+{
+ hmac->innerHashKeyed = 0;
+ hmac->macType = type;
+
+ if (!(type == MD5 || type == SHA || type == SHA256))
+ return -1;
+
+ if (type == MD5)
+ InitMd5(&hmac->hash.md5);
+ else if (type == SHA)
+ InitSha(&hmac->hash.sha);
+#ifndef NO_SHA256
+ else if (type == SHA256)
+ InitSha256(&hmac->hash.sha256);
+#endif
+
+ return 0;
+}
+
+
+void HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
+{
+ byte* ip = (byte*) hmac->ipad;
+ byte* op = (byte*) hmac->opad;
+ word32 i;
+
+ InitHmac(hmac, type);
+
+ if (length <= HMAC_BLOCK_SIZE)
+ XMEMCPY(ip, key, length);
+ else {
+ if (hmac->macType == MD5) {
+ Md5Update(&hmac->hash.md5, key, length);
+ Md5Final(&hmac->hash.md5, ip);
+ length = MD5_DIGEST_SIZE;
+ }
+ else if (hmac->macType == SHA) {
+ ShaUpdate(&hmac->hash.sha, key, length);
+ ShaFinal(&hmac->hash.sha, ip);
+ length = SHA_DIGEST_SIZE;
+ }
+#ifndef NO_SHA256
+ else if (hmac->macType == SHA256) {
+ Sha256Update(&hmac->hash.sha256, key, length);
+ Sha256Final(&hmac->hash.sha256, ip);
+ length = SHA256_DIGEST_SIZE;
+ }
+#endif
+ }
+ XMEMSET(ip + length, 0, HMAC_BLOCK_SIZE - length);
+
+ for(i = 0; i < HMAC_BLOCK_SIZE; i++) {
+ op[i] = ip[i] ^ OPAD;
+ ip[i] ^= IPAD;
+ }
+}
+
+
+static void HmacKeyInnerHash(Hmac* hmac)
+{
+ if (hmac->macType == MD5)
+ Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
+ else if (hmac->macType == SHA)
+ ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
+#ifndef NO_SHA256
+ else if (hmac->macType == SHA256)
+ Sha256Update(&hmac->hash.sha256, (byte*) hmac->ipad, HMAC_BLOCK_SIZE);
+#endif
+
+ hmac->innerHashKeyed = 1;
+}
+
+
+void HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
+{
+ if (!hmac->innerHashKeyed)
+ HmacKeyInnerHash(hmac);
+
+ if (hmac->macType == MD5)
+ Md5Update(&hmac->hash.md5, msg, length);
+ else if (hmac->macType == SHA)
+ ShaUpdate(&hmac->hash.sha, msg, length);
+#ifndef NO_SHA256
+ else if (hmac->macType == SHA256)
+ Sha256Update(&hmac->hash.sha256, msg, length);
+#endif
+
+}
+
+
+void HmacFinal(Hmac* hmac, byte* hash)
+{
+ if (!hmac->innerHashKeyed)
+ HmacKeyInnerHash(hmac);
+
+ if (hmac->macType == MD5) {
+ Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash);
+
+ Md5Update(&hmac->hash.md5, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
+ Md5Update(&hmac->hash.md5, (byte*) hmac->innerHash, MD5_DIGEST_SIZE);
+
+ Md5Final(&hmac->hash.md5, hash);
+ }
+ else if (hmac->macType ==SHA) {
+ ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash);
+
+ ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
+ ShaUpdate(&hmac->hash.sha, (byte*) hmac->innerHash, SHA_DIGEST_SIZE);
+
+ ShaFinal(&hmac->hash.sha, hash);
+ }
+#ifndef NO_SHA256
+ else if (hmac->macType ==SHA256) {
+ Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash);
+
+ Sha256Update(&hmac->hash.sha256, (byte*) hmac->opad, HMAC_BLOCK_SIZE);
+ Sha256Update(&hmac->hash.sha256, (byte*) hmac->innerHash,
+ SHA256_DIGEST_SIZE);
+
+ Sha256Final(&hmac->hash.sha256, hash);
+ }
+#endif
+
+ hmac->innerHashKeyed = 0;
+}
+
+
+#endif /* NO_HMAC */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/integer.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,4280 @@
+/* integer.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca,
+ * http://math.libtomcrypt.com
+ */
+
+
+#ifndef USE_FAST_MATH
+
+#include "integer.h"
+
+
+/* handle up to 6 inits */
+int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
+ mp_int* f)
+{
+ int res = MP_OKAY;
+
+ if (a && ((res = mp_init(a)) != MP_OKAY))
+ return res;
+
+ if (b && ((res = mp_init(b)) != MP_OKAY)) {
+ mp_clear(a);
+ return res;
+ }
+
+ if (c && ((res = mp_init(c)) != MP_OKAY)) {
+ mp_clear(a); mp_clear(b);
+ return res;
+ }
+
+ if (d && ((res = mp_init(d)) != MP_OKAY)) {
+ mp_clear(a); mp_clear(b); mp_clear(c);
+ return res;
+ }
+
+ if (e && ((res = mp_init(e)) != MP_OKAY)) {
+ mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d);
+ return res;
+ }
+
+ if (f && ((res = mp_init(f)) != MP_OKAY)) {
+ mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d); mp_clear(e);
+ return res;
+ }
+
+ return res;
+}
+
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+ int i;
+
+ /* allocate memory required and clear it */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC, 0,
+ DYNAMIC_TYPE_BIGINT);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the digits to zero */
+ for (i = 0; i < MP_PREC; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* set the used to zero, allocated digits to the default precision
+ * and sign to positive */
+ a->used = 0;
+ a->alloc = MP_PREC;
+ a->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+
+
+/* clear one (frees) */
+void
+mp_clear (mp_int * a)
+{
+ int i;
+
+ /* only do anything if a hasn't been freed previously */
+ if (a->dp != NULL) {
+ /* first zero the digits */
+ for (i = 0; i < a->used; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* free ram */
+ XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT);
+
+ /* reset members to make debugging easier */
+ a->dp = NULL;
+ a->alloc = a->used = 0;
+ a->sign = MP_ZPOS;
+ }
+}
+
+
+/* get the size for an unsigned equivalent */
+int mp_unsigned_bin_size (mp_int * a)
+{
+ int size = mp_count_bits (a);
+ return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+ int r;
+ mp_digit q;
+
+ /* shortcut */
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits and add that */
+ r = (a->used - 1) * DIGIT_BIT;
+
+ /* take the last digit and count the bits in it */
+ q = a->dp[a->used - 1];
+ while (q > ((mp_digit) 0)) {
+ ++r;
+ q >>= ((mp_digit) 1);
+ }
+ return r;
+}
+
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+ int x, res;
+ mp_int t;
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ x = 0;
+ while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+ b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+ b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+ if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+ bn_reverse (b, x);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_init (a)) != MP_OKAY) {
+ return res;
+ }
+ return mp_copy (b, a);
+}
+
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+ int res, n;
+
+ /* if dst == src do nothing */
+ if (a == b) {
+ return MP_OKAY;
+ }
+
+ /* grow dest */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero b and copy the parameters over */
+ {
+ register mp_digit *tmpa, *tmpb;
+
+ /* pointer aliases */
+
+ /* source */
+ tmpa = a->dp;
+
+ /* destination */
+ tmpb = b->dp;
+
+ /* copy all the digits */
+ for (n = 0; n < a->used; n++) {
+ *tmpb++ = *tmpa++;
+ }
+
+ /* clear high digits */
+ for (; n < b->used; n++) {
+ *tmpb++ = 0;
+ }
+ }
+
+ /* copy used count and sign */
+ b->used = a->used;
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+ int i;
+ mp_digit *tmp;
+
+ /* if the alloc size is smaller alloc more ram */
+ if (a->alloc < size) {
+ /* ensure there are always at least MP_PREC digits extra on top */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* reallocate the array a->dp
+ *
+ * We store the return in a temporary variable
+ * in case the operation failed we don't want
+ * to overwrite the dp member of a.
+ */
+ tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, 0,
+ DYNAMIC_TYPE_BIGINT);
+ if (tmp == NULL) {
+ /* reallocation failed but "a" is still valid [can be freed] */
+ return MP_MEM;
+ }
+
+ /* reallocation succeeded so set a->dp */
+ a->dp = tmp;
+
+ /* zero excess digits */
+ i = a->alloc;
+ a->alloc = size;
+ for (; i < a->alloc; i++) {
+ a->dp[i] = 0;
+ }
+ }
+ return MP_OKAY;
+}
+
+
+/* reverse an array, used for radix code */
+void
+bn_reverse (unsigned char *s, int len)
+{
+ int ix, iy;
+ unsigned char t;
+
+ ix = 0;
+ iy = len - 1;
+ while (ix < iy) {
+ t = s[ix];
+ s[ix] = s[iy];
+ s[iy] = t;
+ ++ix;
+ --iy;
+ }
+}
+
+
+/* shift right by a certain bit count (store quotient in c, optional
+ remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+ mp_digit D, r, rr;
+ int x, res;
+ mp_int t;
+
+
+ /* if the shift count is <= 0 then we do no work */
+ if (b <= 0) {
+ res = mp_copy (a, c);
+ if (d != NULL) {
+ mp_zero (d);
+ }
+ return res;
+ }
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ /* get the remainder */
+ if (d != NULL) {
+ if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ mp_rshd (c, b / DIGIT_BIT);
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ D = (mp_digit) (b % DIGIT_BIT);
+ if (D != 0) {
+ register mp_digit *tmpc, mask, shift;
+
+ /* mask */
+ mask = (((mp_digit)1) << D) - 1;
+
+ /* shift for lsb */
+ shift = DIGIT_BIT - D;
+
+ /* alias */
+ tmpc = c->dp + (c->used - 1);
+
+ /* carry */
+ r = 0;
+ for (x = c->used - 1; x >= 0; x--) {
+ /* get the lower bits of this word in a temp */
+ rr = *tmpc & mask;
+
+ /* shift the current word and mix in the carry bits from the previous
+ word */
+ *tmpc = (*tmpc >> D) | (r << shift);
+ --tmpc;
+
+ /* set the carry to the carry bits of the current word found above */
+ r = rr;
+ }
+ }
+ mp_clamp (c);
+ if (d != NULL) {
+ mp_exch (&t, d);
+ }
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+ int n;
+ mp_digit *tmp;
+
+ a->sign = MP_ZPOS;
+ a->used = 0;
+
+ tmp = a->dp;
+ for (n = 0; n < a->alloc; n++) {
+ *tmp++ = 0;
+ }
+}
+
+
+/* trim unused digits
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast. Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+ /* decrease used while the most significant digit is
+ * zero.
+ */
+ while (a->used > 0 && a->dp[a->used - 1] == 0) {
+ --(a->used);
+ }
+
+ /* reset the sign flag if used == 0 */
+ if (a->used == 0) {
+ a->sign = MP_ZPOS;
+ }
+}
+
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+ mp_int t;
+
+ t = *a;
+ *a = *b;
+ *b = t;
+}
+
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+ int x;
+
+ /* if b <= 0 then ignore it */
+ if (b <= 0) {
+ return;
+ }
+
+ /* if b > used then simply zero it and return */
+ if (a->used <= b) {
+ mp_zero (a);
+ return;
+ }
+
+ {
+ register mp_digit *bottom, *top;
+
+ /* shift the digits down */
+
+ /* bottom */
+ bottom = a->dp;
+
+ /* top [offset into digits] */
+ top = a->dp + b;
+
+ /* this is implemented as a sliding window where
+ * the window is b-digits long and digits from
+ * the top of the window are copied to the bottom
+ *
+ * e.g.
+
+ b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
+ /\ | ---->
+ \-------------------/ ---->
+ */
+ for (x = 0; x < (a->used - b); x++) {
+ *bottom++ = *top++;
+ }
+
+ /* zero the top digits */
+ for (; x < a->used; x++) {
+ *bottom++ = 0;
+ }
+ }
+
+ /* remove excess digits */
+ a->used -= b;
+}
+
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+ int x, res;
+
+ /* if b is <= 0 then zero the int */
+ if (b <= 0) {
+ mp_zero (c);
+ return MP_OKAY;
+ }
+
+ /* if the modulus is larger than the value than return */
+ if (b >= (int) (a->used * DIGIT_BIT)) {
+ res = mp_copy (a, c);
+ return res;
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+
+ /* zero digits above the last digit of the modulus */
+ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+ c->dp[x] = 0;
+ }
+ /* clear the digit that is not completely outside/inside the modulus */
+ c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) <<
+ (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+ int res;
+
+ /* make sure there are at least two digits */
+ if (a->alloc < 2) {
+ if ((res = mp_grow(a, 2)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero the int */
+ mp_zero (a);
+
+ /* read the bytes in */
+ while (c-- > 0) {
+ if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+ return res;
+ }
+
+#ifndef MP_8BIT
+ a->dp[0] |= *b++;
+ a->used += 1;
+#else
+ a->dp[0] = (*b & MP_MASK);
+ a->dp[1] |= ((*b++ >> 7U) & 1);
+ a->used += 2;
+#endif
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+ mp_digit d;
+ int res;
+
+ /* copy */
+ if (a != c) {
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+ if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ d = (mp_digit) (b % DIGIT_BIT);
+ if (d != 0) {
+ register mp_digit *tmpc, shift, mask, r, rr;
+ register int x;
+
+ /* bitmask for carries */
+ mask = (((mp_digit)1) << d) - 1;
+
+ /* shift for msbs */
+ shift = DIGIT_BIT - d;
+
+ /* alias */
+ tmpc = c->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < c->used; x++) {
+ /* get the higher bits of the current word */
+ rr = (*tmpc >> shift) & mask;
+
+ /* shift the current word and OR in the carry */
+ *tmpc = ((*tmpc << d) | r) & MP_MASK;
+ ++tmpc;
+
+ /* set the carry to the carry bits of the current word */
+ r = rr;
+ }
+
+ /* set final carry */
+ if (r != 0) {
+ c->dp[(c->used)++] = r;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+ int x, res;
+
+ /* if its less than zero return */
+ if (b <= 0) {
+ return MP_OKAY;
+ }
+
+ /* grow to fit the new digits */
+ if (a->alloc < a->used + b) {
+ if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ {
+ register mp_digit *top, *bottom;
+
+ /* increment the used by the shift amount then copy upwards */
+ a->used += b;
+
+ /* top */
+ top = a->dp + a->used - 1;
+
+ /* base */
+ bottom = a->dp + a->used - 1 - b;
+
+ /* much like mp_rshd this is implemented using a sliding window
+ * except the window goes the otherway around. Copying from
+ * the bottom to the top. see bn_mp_rshd.c for more info.
+ */
+ for (x = a->used - 1; x >= b; x--) {
+ *top-- = *bottom--;
+ }
+
+ /* zero the lower digits */
+ top = a->dp;
+ for (x = 0; x < b; x++) {
+ *top++ = 0;
+ }
+ }
+ return MP_OKAY;
+}
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions. Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+ int dr;
+
+ /* modulus P must be positive */
+ if (P->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* if exponent X is negative we have to recurse */
+ if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+ mp_int tmpG, tmpX;
+ int err;
+
+ /* first compute 1/G mod P */
+ if ((err = mp_init(&tmpG)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+
+ /* now get |X| */
+ if ((err = mp_init(&tmpX)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+ if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ mp_clear(&tmpX);
+ return err;
+ }
+
+ /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+ err = mp_exptmod(&tmpG, &tmpX, P, Y);
+ mp_clear(&tmpG);
+ mp_clear(&tmpX);
+ return err;
+#else
+ /* no invmod */
+ return MP_VAL;
+#endif
+ }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && \
+ defined(BN_S_MP_EXPTMOD_C)
+ if (mp_reduce_is_2k_l(P) == MP_YES) {
+ return s_mp_exptmod(G, X, P, Y, 1);
+ }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+ /* is it a DR modulus? */
+ dr = mp_dr_is_modulus(P);
+#else
+ /* default to no */
+ dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+ /* if not, is it a unrestricted DR modulus? */
+ if (dr == 0) {
+ dr = mp_reduce_is_2k(P) << 1;
+ }
+#endif
+
+ /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+ if (mp_isodd (P) == 1 || dr != 0) {
+ return mp_exptmod_fast (G, X, P, Y, dr);
+ } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+ /* otherwise use the generic Barrett reduction technique */
+ return s_mp_exptmod (G, X, P, Y, 0);
+#else
+ /* no exptmod for evens */
+ return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+ }
+#endif
+}
+
+
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+ int res;
+
+ /* copy a to b */
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* force the sign of b to positive */
+ b->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+#ifdef BN_FAST_MP_INVMOD_C
+ /* if the modulus is odd we can use a faster routine instead */
+ if (mp_isodd (b) == 1) {
+ return fast_mp_invmod (a, b, c);
+ }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+ return mp_invmod_slow(a, b, c);
+#endif
+}
+
+
+/* computes the modular inverse via binary extended euclidean algorithm,
+ * that is c = 1/a mod b
+ *
+ * Based on slow invmod except this is optimized for the case where b is
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, B, D;
+ int res, neg;
+
+ /* 2. [modified] b must be odd */
+ if (mp_iseven (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init all our temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x == modulus, y == value to invert */
+ if ((res = mp_copy (b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* we need y = |a| */
+ if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if B is odd then */
+ if (mp_isodd (&B) == 1) {
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* B = B/2 */
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if D is odd then */
+ if (mp_isodd (&D) == 1) {
+ /* D = (D-x)/2 */
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* D = D/2 */
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0) {
+ goto top;
+ }
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* b is now the inverse */
+ neg = a->sign;
+ while (D.sign == MP_NEG) {
+ if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ mp_exch (&D, c);
+ c->sign = neg;
+ res = MP_OKAY;
+
+LBL_ERR:mp_clear(&x);
+ mp_clear(&y);
+ mp_clear(&u);
+ mp_clear(&v);
+ mp_clear(&B);
+ mp_clear(&D);
+ return res;
+}
+
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, A, B, C, D;
+ int res;
+
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v,
+ &A, &B)) != MP_OKAY) {
+ return res;
+ }
+
+ /* init rest of tmps temps */
+ if ((res = mp_init_multi(&C, &D, 0, 0, 0, 0)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x = a, y = b */
+ if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 2. [modified] if x,y are both even then return an error! */
+ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&A, 1);
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (mp_iseven (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if A or B is odd then */
+ if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+ /* A = (A+y)/2, B = (B-x)/2 */
+ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* A = A/2, B = B/2 */
+ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (mp_iseven (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if C or D is odd then */
+ if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+ /* C = (C+y)/2, D = (D-x)/2 */
+ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* C = C/2, D = D/2 */
+ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, A = A - C, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, C = C - A, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (mp_iszero (&u) == 0)
+ goto top;
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* if its too low */
+ while (mp_cmp_d(&C, 0) == MP_LT) {
+ if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* too big */
+ while (mp_cmp_mag(&C, b) != MP_LT) {
+ if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* C is now the inverse */
+ mp_exch (&C, c);
+ res = MP_OKAY;
+LBL_ERR:mp_clear(&x);
+ mp_clear(&y);
+ mp_clear(&u);
+ mp_clear(&v);
+ mp_clear(&A);
+ mp_clear(&B);
+ mp_clear(&C);
+ mp_clear(&D);
+ return res;
+}
+
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+ int n;
+ mp_digit *tmpa, *tmpb;
+
+ /* compare based on # of non-zero digits */
+ if (a->used > b->used) {
+ return MP_GT;
+ }
+
+ if (a->used < b->used) {
+ return MP_LT;
+ }
+
+ /* alias for a */
+ tmpa = a->dp + (a->used - 1);
+
+ /* alias for b */
+ tmpb = b->dp + (a->used - 1);
+
+ /* compare based on digits */
+ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+ if (*tmpa > *tmpb) {
+ return MP_GT;
+ }
+
+ if (*tmpa < *tmpb) {
+ return MP_LT;
+ }
+ }
+ return MP_EQ;
+}
+
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+ /* compare based on sign */
+ if (a->sign != b->sign) {
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ } else {
+ return MP_GT;
+ }
+ }
+
+ /* compare digits */
+ if (a->sign == MP_NEG) {
+ /* if negative compare opposite direction */
+ return mp_cmp_mag(b, a);
+ } else {
+ return mp_cmp_mag(a, b);
+ }
+}
+
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+ /* compare based on sign */
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ }
+
+ /* compare based on magnitude */
+ if (a->used > 1) {
+ return MP_GT;
+ }
+
+ /* compare the only digit of a to b */
+ if (a->dp[0] > b) {
+ return MP_GT;
+ } else if (a->dp[0] < b) {
+ return MP_LT;
+ } else {
+ return MP_EQ;
+ }
+}
+
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+ mp_zero (a);
+ a->dp[0] = b & MP_MASK;
+ a->used = (a->dp[0] != 0) ? 1 : 0;
+}
+
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int t;
+ int res;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ if (t.sign != b->sign) {
+ res = mp_add (b, &t, c);
+ } else {
+ res = MP_OKAY;
+ mp_exch (&t, c);
+ }
+
+ mp_clear (&t);
+ return res;
+}
+
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ mp_int ta, tb, tq, q;
+ int res, n, n2;
+
+ /* is divisor zero ? */
+ if (mp_iszero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ /* init our temps */
+ if ((res = mp_init_multi(&ta, &tb, &tq, &q, 0, 0) != MP_OKAY)) {
+ return res;
+ }
+
+
+ mp_set(&tq, 1);
+ n = mp_count_bits(a) - mp_count_bits(b);
+ if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+ ((res = mp_abs(b, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+ ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+
+ while (n-- >= 0) {
+ if (mp_cmp(&tb, &ta) != MP_GT) {
+ if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+ ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+ if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+ ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* now q == quotient and ta == remainder */
+ n = a->sign;
+ n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+ if (c != NULL) {
+ mp_exch(c, &q);
+ c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+ }
+ if (d != NULL) {
+ mp_exch(d, &ta);
+ d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+ }
+LBL_ERR:
+ mp_clear(&ta);
+ mp_clear(&tb);
+ mp_clear(&tq);
+ mp_clear(&q);
+ return res;
+}
+
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* copy */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* source alias */
+ tmpa = a->dp + b->used - 1;
+
+ /* dest alias */
+ tmpb = b->dp + b->used - 1;
+
+ /* carry */
+ r = 0;
+ for (x = b->used - 1; x >= 0; x--) {
+ /* get the carry for the next iteration */
+ rr = *tmpa & 1;
+
+ /* shift the current digit, add in carry and store */
+ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+ /* forward carry to next iteration */
+ r = rr;
+ }
+
+ /* zero excess digits */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ mp_clamp (b);
+ return MP_OKAY;
+}
+
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ /* get sign of both inputs */
+ sa = a->sign;
+ sb = b->sign;
+
+ /* handle two cases, not four */
+ if (sa == sb) {
+ /* both positive or both negative */
+ /* add their magnitudes, copy the sign */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* one positive, the other negative */
+ /* subtract the one with the greater magnitude from */
+ /* the one of the lesser magnitude. The result gets */
+ /* the sign of the one with the greater magnitude. */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ c->sign = sb;
+ res = s_mp_sub (b, a, c);
+ } else {
+ c->sign = sa;
+ res = s_mp_sub (a, b, c);
+ }
+ }
+ return res;
+}
+
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int *x;
+ int olduse, res, min, max;
+
+ /* find sizes, we let |a| <= |b| which means we have to sort
+ * them. "x" will point to the input with the most digits
+ */
+ if (a->used > b->used) {
+ min = b->used;
+ max = a->used;
+ x = a;
+ } else {
+ min = a->used;
+ max = b->used;
+ x = b;
+ }
+
+ /* init result */
+ if (c->alloc < max + 1) {
+ if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get old used digit count and set new one */
+ olduse = c->used;
+ c->used = max + 1;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+
+ /* first input */
+ tmpa = a->dp;
+
+ /* second input */
+ tmpb = b->dp;
+
+ /* destination */
+ tmpc = c->dp;
+
+ /* zero the carry */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+ *tmpc = *tmpa++ + *tmpb++ + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, that is in A+B
+ * if A or B has more digits add those in
+ */
+ if (min != max) {
+ for (; i < max; i++) {
+ /* T[i] = X[i] + U */
+ *tmpc = x->dp[i] + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* add carry */
+ *tmpc++ = u;
+
+ /* clear digits above oldused */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int olduse, res, min, max;
+
+ /* find sizes */
+ min = b->used;
+ max = a->used;
+
+ /* init result */
+ if (c->alloc < max) {
+ if ((res = mp_grow (c, max)) != MP_OKAY) {
+ return res;
+ }
+ }
+ olduse = c->used;
+ c->used = max;
+
+ {
+ register mp_digit u, *tmpa, *tmpb, *tmpc;
+ register int i;
+
+ /* alias for digit pointers */
+ tmpa = a->dp;
+ tmpb = b->dp;
+ tmpc = c->dp;
+
+ /* set carry to zero */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* T[i] = A[i] - B[i] - U */
+ *tmpc = *tmpa++ - *tmpb++ - u;
+
+ /* U = carry bit of T[i]
+ * Note this saves performing an AND operation since
+ * if a carry does occur it will propagate all the way to the
+ * MSB. As a result a single shift is enough to get the carry
+ */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, e.g. if A has more digits than B */
+ for (; i < max; i++) {
+ /* T[i] = A[i] - U */
+ *tmpc = *tmpa++ - u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* clear digits above used (since we may not have grown result above) */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ sa = a->sign;
+ sb = b->sign;
+
+ if (sa != sb) {
+ /* subtract a negative from a positive, OR */
+ /* subtract a positive from a negative. */
+ /* In either case, ADD their magnitudes, */
+ /* and use the sign of the first number. */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* subtract a positive from a positive, OR */
+ /* subtract a negative from a negative. */
+ /* First, take the difference between their */
+ /* magnitudes, then... */
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ /* Copy the sign from the first */
+ c->sign = sa;
+ /* The first has a larger or equal magnitude */
+ res = s_mp_sub (a, b, c);
+ } else {
+ /* The result has the *opposite* sign from */
+ /* the first number. */
+ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ /* The second has a larger magnitude */
+ res = s_mp_sub (b, a, c);
+ }
+ }
+ return res;
+}
+
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+ int ix, iy;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ /* if more than half of the digits are -1 we're sold */
+ for (iy = ix = 0; ix < a->used; ix++) {
+ if (a->dp[ix] == MP_MASK) {
+ ++iy;
+ }
+ }
+ return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+
+ }
+ return MP_NO;
+}
+
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+ int ix, iy, iw;
+ mp_digit iz;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ iy = mp_count_bits(a);
+ iz = 1;
+ iw = 1;
+
+ /* Test every bit from the second digit up, must be 1 */
+ for (ix = DIGIT_BIT; ix < iy; ix++) {
+ if ((a->dp[iw] & iz) == 0) {
+ return MP_NO;
+ }
+ iz <<= 1;
+ if (iz > (mp_digit)MP_MASK) {
+ ++iw;
+ iz = 1;
+ }
+ }
+ }
+ return MP_YES;
+}
+
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+ int ix;
+
+ /* must be at least two digits */
+ if (a->used < 2) {
+ return 0;
+ }
+
+ /* must be of the form b**k - a [a <= b] so all
+ * but the first digit must be equal to -1 (mod b).
+ */
+ for (ix = 1; ix < a->used; ix++) {
+ if (a->dp[ix] != MP_MASK) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular
+ * exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y,
+ int redmode)
+{
+ mp_int M[TAB_SIZE], res;
+ mp_digit buf, mp;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+ /* use a pointer to the reduction algorithm. This allows us to use
+ * one of many reduction algorithms without modding the guts of
+ * the code with if statements everywhere.
+ */
+ int (*redux)(mp_int*,mp_int*,mp_digit);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* determine and setup reduction code */
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+ /* now setup montgomery */
+ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+
+ /* automatically pick the comba one if available (saves quite a few
+ calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+ if (((P->used * 2 + 1) < MP_WARRAY) &&
+ P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ redux = fast_mp_montgomery_reduce;
+ } else
+#endif
+ {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+ /* use slower baseline Montgomery method */
+ redux = mp_montgomery_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+ } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+ /* setup DR reduction for moduli of the form B**k - b */
+ mp_dr_setup(P, &mp);
+ redux = mp_dr_reduce;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+ /* setup DR reduction for moduli of the form 2**k - b */
+ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+ redux = mp_reduce_2k;
+#else
+ err = MP_VAL;
+ goto LBL_M;
+#endif
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ /* create M table
+ *
+
+ *
+ * The first half of the table is not computed though accept for M[0] and M[1]
+ */
+
+ if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+ /* now we need R mod m */
+ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+#else
+ err = MP_VAL;
+ goto LBL_RES;
+#endif
+
+ /* now set M[1] to G * R mod m */
+ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ } else {
+ mp_set(&res, 1);
+ if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times*/
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* create upper table */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits so break */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int)DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* get next bit of the window */
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ if (redmode == 0) {
+ /* fixup result if Montgomery reduction is used
+ * recall that any value in a Montgomery system is
+ * actually multiplied by R mod n. So we have
+ * to reduce one more time to cancel out the factor
+ * of R.
+ */
+ if ((err = redux(&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* swap res with Y */
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+ mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
+ * => 2*X*A - X*X*A*A = 1
+ * => 2*(1) - (1) = 1
+ */
+ b = n->dp[0];
+
+ if ((b & 1) == 0) {
+ return MP_VAL;
+ }
+
+ x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+ x *= 2 - b * x; /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+ x *= 2 - b * x; /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+ x *= 2 - b * x; /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+ x *= 2 - b * x; /* here x*a==1 mod 2**64 */
+#endif
+
+ /* rho = -1/m mod b */
+ /* TAO, switched mp_word casts to mp_digit to shut up compiler */
+ *rho = (((mp_digit)1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK;
+
+ return MP_OKAY;
+}
+
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, olduse;
+ mp_word W[MP_WARRAY];
+
+ /* get old used count */
+ olduse = x->used;
+
+ /* grow a as required */
+ if (x->alloc < n->used + 1) {
+ if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* first we have to get the digits of the input into
+ * an array of double precision words W[...]
+ */
+ {
+ register mp_word *_W;
+ register mp_digit *tmpx;
+
+ /* alias for the W[] array */
+ _W = W;
+
+ /* alias for the digits of x*/
+ tmpx = x->dp;
+
+ /* copy the digits of a into W[0..a->used-1] */
+ for (ix = 0; ix < x->used; ix++) {
+ *_W++ = *tmpx++;
+ }
+
+ /* zero the high words of W[a->used..m->used*2] */
+ for (; ix < n->used * 2 + 1; ix++) {
+ *_W++ = 0;
+ }
+ }
+
+ /* now we proceed to zero successive digits
+ * from the least significant upwards
+ */
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * m' mod b
+ *
+ * We avoid a double precision multiplication (which isn't required)
+ * by casting the value down to a mp_digit. Note this requires
+ * that W[ix-1] have the carry cleared (see after the inner loop)
+ */
+ register mp_digit mu;
+ mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i
+ *
+ * This is computed in place and on the fly. The multiplication
+ * by b**i is handled by offseting which columns the results
+ * are added to.
+ *
+ * Note the comba method normally doesn't handle carries in the
+ * inner loop In this case we fix the carry from the previous
+ * column since the Montgomery reduction requires digits of the
+ * result (so far) [see above] to work. This is
+ * handled by fixing up one carry after the inner loop. The
+ * carry fixups are done in order so after these loops the
+ * first m->used words of W[] have the carries fixed
+ */
+ {
+ register int iy;
+ register mp_digit *tmpn;
+ register mp_word *_W;
+
+ /* alias for the digits of the modulus */
+ tmpn = n->dp;
+
+ /* Alias for the columns set by an offset of ix */
+ _W = W + ix;
+
+ /* inner loop */
+ for (iy = 0; iy < n->used; iy++) {
+ *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+ }
+ }
+
+ /* now fix carry for next digit, W[ix+1] */
+ W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* now we have to propagate the carries and
+ * shift the words downward [all those least
+ * significant digits we zeroed].
+ */
+ {
+ register mp_digit *tmpx;
+ register mp_word *_W, *_W1;
+
+ /* nox fix rest of carries */
+
+ /* alias for current word */
+ _W1 = W + ix;
+
+ /* alias for next word, where the carry goes */
+ _W = W + ++ix;
+
+ for (; ix <= n->used * 2 + 1; ix++) {
+ *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* copy out, A = A/b**n
+ *
+ * The result is A/b**n but instead of converting from an
+ * array of mp_word to mp_digit than calling mp_rshd
+ * we just copy them in the right order
+ */
+
+ /* alias for destination word */
+ tmpx = x->dp;
+
+ /* alias for shifted double precision result */
+ _W = W + n->used;
+
+ for (ix = 0; ix < n->used + 1; ix++) {
+ *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+ }
+
+ /* zero oldused digits, if the input a was larger than
+ * m->used+1 we'll have to clear the digits
+ */
+ for (; ix < olduse; ix++) {
+ *tmpx++ = 0;
+ }
+ }
+
+ /* set the max used and clamp */
+ x->used = n->used + 1;
+ mp_clamp (x);
+
+ /* if A >= m then A = A - m */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+ return MP_OKAY;
+}
+
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, digs;
+ mp_digit mu;
+
+ /* can the fast reduction [comba] method be used?
+ *
+ * Note that unlike in mul you're safely allowed *less*
+ * than the available columns [255 per default] since carries
+ * are fixed up in the inner loop.
+ */
+ digs = n->used * 2 + 1;
+ if ((digs < MP_WARRAY) &&
+ n->used <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_mp_montgomery_reduce (x, n, rho);
+ }
+
+ /* grow the input as required */
+ if (x->alloc < digs) {
+ if ((res = mp_grow (x, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+ x->used = digs;
+
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * rho mod b
+ *
+ * The value of rho must be precalculated via
+ * montgomery_setup() such that
+ * it equals -1/n0 mod b this allows the
+ * following inner loop to reduce the
+ * input one digit at a time
+ */
+ mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i */
+ {
+ register int iy;
+ register mp_digit *tmpn, *tmpx, u;
+ register mp_word r;
+
+ /* alias for digits of the modulus */
+ tmpn = n->dp;
+
+ /* alias for the digits of x [the input] */
+ tmpx = x->dp + ix;
+
+ /* set the carry to zero */
+ u = 0;
+
+ /* Multiply and add in place */
+ for (iy = 0; iy < n->used; iy++) {
+ /* compute product and sum */
+ r = ((mp_word)mu) * ((mp_word)*tmpn++) +
+ ((mp_word) u) + ((mp_word) * tmpx);
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* fix digit */
+ *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+ }
+ /* At this point the ix'th digit of x should be zero */
+
+
+ /* propagate carries upwards as required*/
+ while (u) {
+ *tmpx += u;
+ u = *tmpx >> DIGIT_BIT;
+ *tmpx++ &= MP_MASK;
+ }
+ }
+ }
+
+ /* at this point the n.used'th least
+ * significant digits of x are all zero
+ * which means we can shift x to the
+ * right by n.used digits and the
+ * residue is unchanged.
+ */
+
+ /* x = x/b**n.used */
+ mp_clamp(x);
+ mp_rshd (x, n->used);
+
+ /* if x >= n then x = x - n */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+
+ return MP_OKAY;
+}
+
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+ /* the casts are required if DIGIT_BIT is one less than
+ * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+ */
+ *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
+ ((mp_word)a->dp[0]));
+}
+
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ * Chae Hoon Lim, Pil Joong Lee,
+ * POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+ int err, i, m;
+ mp_word r;
+ mp_digit mu, *tmpx1, *tmpx2;
+
+ /* m = digits in modulus */
+ m = n->used;
+
+ /* ensure that "x" has at least 2m digits */
+ if (x->alloc < m + m) {
+ if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+ /* aliases for digits */
+ /* alias for lower half of x */
+ tmpx1 = x->dp;
+
+ /* alias for upper half of x, or x/B**m */
+ tmpx2 = x->dp + m;
+
+ /* set carry to zero */
+ mu = 0;
+
+ /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+ for (i = 0; i < m; i++) {
+ r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+ *tmpx1++ = (mp_digit)(r & MP_MASK);
+ mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+ }
+
+ /* set final carry */
+ *tmpx1++ = mu;
+
+ /* zero words above m */
+ for (i = m + 1; i < x->used; i++) {
+ *tmpx1++ = 0;
+ }
+
+ /* clamp, sub and return */
+ mp_clamp (x);
+
+ /* if x >= n then subtract and reduce again
+ * Each successive "recursion" makes the input smaller and smaller.
+ */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ s_mp_sub(x, n, x);
+ goto top;
+ }
+ return MP_OKAY;
+}
+
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (d != 1) {
+ /* q = q * d */
+ if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+ int res, p;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(a);
+ if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ *d = tmp.dp[0];
+ mp_clear(&tmp);
+ return MP_OKAY;
+}
+
+
+/* computes a = 2**b
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+ int res;
+
+ /* zero a as per default */
+ mp_zero (a);
+
+ /* grow a to accomodate the single bit */
+ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set the used count of where the bit will go */
+ a->used = b / DIGIT_BIT + 1;
+
+ /* put the single bit in its place */
+ a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+ return MP_OKAY;
+}
+
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit u, *tmpa, *tmpc;
+ mp_word r;
+ int ix, res, olduse;
+
+ /* make sure c is big enough to hold a*b */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get the original destinations used count */
+ olduse = c->used;
+
+ /* set the sign */
+ c->sign = a->sign;
+
+ /* alias for a->dp [source] */
+ tmpa = a->dp;
+
+ /* alias for c->dp [dest] */
+ tmpc = c->dp;
+
+ /* zero carry */
+ u = 0;
+
+ /* compute columns */
+ for (ix = 0; ix < a->used; ix++) {
+ /* compute product and carry sum for this term */
+ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+ /* mask off higher bits to get a single digit */
+ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* send carry into next iteration */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+
+ /* store final carry [if any] and increment ix offset */
+ *tmpc++ = u;
+ ++ix;
+
+ /* now zero digits above the top */
+ while (ix++ < olduse) {
+ *tmpc++ = 0;
+ }
+
+ /* set used count */
+ c->used = a->used + 1;
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+
+
+/* d = a * b (mod c) */
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+ int res;
+
+ {
+#ifdef BN_FAST_S_MP_SQR_C
+ /* can we use the fast comba multiplier? */
+ if ((a->used * 2 + 1) < MP_WARRAY &&
+ a->used <
+ (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+ res = fast_s_mp_sqr (a, b);
+ } else
+#endif
+#ifdef BN_S_MP_SQR_C
+ res = s_mp_sqr (a, b);
+#else
+ res = MP_VAL;
+#endif
+ }
+ b->sign = MP_ZPOS;
+ return res;
+}
+
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, neg;
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+ {
+ /* can we use the fast multiplier?
+ *
+ * The fast multiplier can be used if the output will
+ * have less than MP_WARRAY digits and the number of
+ * digits won't affect carry propagation
+ */
+ int digs = a->used + b->used + 1;
+
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+ if ((digs < MP_WARRAY) &&
+ MIN(a->used, b->used) <=
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ res = fast_s_mp_mul_digs (a, b, c, digs);
+ } else
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+ res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+ res = MP_VAL;
+#endif
+
+ }
+ c->sign = (c->used > 0) ? neg : MP_ZPOS;
+ return res;
+}
+
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* grow to accomodate result */
+ if (b->alloc < a->used + 1) {
+ if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+
+ {
+ register mp_digit r, rr, *tmpa, *tmpb;
+
+ /* alias for source */
+ tmpa = a->dp;
+
+ /* alias for dest */
+ tmpb = b->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < a->used; x++) {
+
+ /* get what will be the *next* carry bit from the
+ * MSB of the current digit
+ */
+ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+ /* now shift up this digit, add in the carry [from the previous] */
+ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+
+ /* copy the carry that would be from the source
+ * digit into the next iteration
+ */
+ r = rr;
+ }
+
+ /* new leading digit? */
+ if (r != 0) {
+ /* add a MSB which is always 1 at this point */
+ *tmpb = 1;
+ ++(b->used);
+ }
+
+ /* now zero any excess digits on the destination
+ * that we didn't write to
+ */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w, t;
+ mp_digit b;
+ int res, ix;
+
+ /* b = 2**DIGIT_BIT / 3 */
+ b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= 3) {
+ /* multiply w by [1/3] */
+ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+ /* now subtract 3 * [w/3] from w, to get the remainder */
+ w -= t+t+t;
+
+ /* fixup the remainder as required since
+ * the optimization is not exact.
+ */
+ while (w >= 3) {
+ t += 1;
+ w -= 3;
+ }
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ /* [optional] store the remainder */
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ /* [optional] store the quotient */
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+ int x;
+
+ /* pad size so there are always extra digits */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* alloc mem */
+ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, 0,
+ DYNAMIC_TYPE_BIGINT);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the members */
+ a->used = 0;
+ a->alloc = size;
+ a->sign = MP_ZPOS;
+
+ /* zero the digits */
+ for (x = 0; x < size; x++) {
+ a->dp[x] = 0;
+ }
+
+ return MP_OKAY;
+}
+
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that
+ * starts closer to zero] can't equal the offset of tmpy.
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens. You double all those
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY], *tmpx;
+ mp_word W1;
+
+ /* grow the destination as required */
+ pa = a->used + a->used;
+ if (b->alloc < pa) {
+ if ((res = mp_grow (b, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ W1 = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_word _W;
+ mp_digit *tmpy;
+
+ /* clear counter */
+ _W = 0;
+
+ /* get offsets into the two bignums */
+ ty = MIN(a->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = a->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* now for squaring tx can never equal ty
+ * we halve the distance since they approach at a rate of 2x
+ * and we have to round because odd cases need to be executed
+ */
+ iy = MIN(iy, (ty-tx+1)>>1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* double the inner product and add carry */
+ _W = _W + _W + W1;
+
+ /* even columns have the square term in them */
+ if ((ix&1) == 0) {
+ _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+ }
+
+ /* store it */
+ W[ix] = (mp_digit)(_W & MP_MASK);
+
+ /* make next carry */
+ W1 = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = b->used;
+ b->used = a->used+a->used;
+
+ {
+ mp_digit *tmpb;
+ tmpb = b->dp;
+ for (ix = 0; ix < pa; ix++) {
+ *tmpb++ = W[ix] & MP_MASK;
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpb++ = 0;
+ }
+ }
+ mp_clamp (b);
+ return MP_OKAY;
+}
+
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier. It is
+ * designed to compute the columns of the product first
+ * then handle the carries afterwards. This has the effect
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of
+ * digits of output so if say only a half-product is required
+ * you don't have to compute the upper half (a feature
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ register mp_word _W;
+
+ /* grow the destination as required */
+ if (c->alloc < digs) {
+ if ((res = mp_grow (c, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = MIN(digs, a->used + b->used);
+
+ /* clear the carry */
+ _W = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty;
+ int iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; ++iz) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+ tmpc = c->dp;
+ for (ix = 0; ix < pa+1; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+ mp_int t;
+ int res, ix, iy, pa;
+ mp_word r;
+ mp_digit u, tmpx, *tmpt;
+
+ pa = a->used;
+ if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* default used is maximum possible size */
+ t.used = 2*pa + 1;
+
+ for (ix = 0; ix < pa; ix++) {
+ /* first calculate the digit at 2*ix */
+ /* calculate double precision result */
+ r = ((mp_word) t.dp[2*ix]) +
+ ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+ /* store lower part in result */
+ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* left hand side of A[ix] * A[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias for where to store the results */
+ tmpt = t.dp + (2*ix + 1);
+
+ for (iy = ix + 1; iy < pa; iy++) {
+ /* first calculate the product */
+ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+ /* now calculate the double precision result, note we use
+ * addition instead of *2 since it's easier to optimize
+ */
+ r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+ /* store lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ /* propagate upwards */
+ while (u != ((mp_digit) 0)) {
+ r = ((mp_word) *tmpt) + ((mp_word) u);
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, b);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12 Modified so you can control how
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+ if (((digs) < MP_WARRAY) &&
+ MIN (a->used, b->used) <
+ (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_digs (a, b, c, digs);
+ }
+
+ if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+ return res;
+ }
+ t.used = digs;
+
+ /* compute the digits of the product directly */
+ pa = a->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* set the carry to zero */
+ u = 0;
+
+ /* limit ourselves to making digs digits of output */
+ pb = MIN (b->used, digs - ix);
+
+ /* setup some aliases */
+ /* copy of the digit from a used within the nested loop */
+ tmpx = a->dp[ix];
+
+ /* an alias for the destination shifted ix places */
+ tmpt = t.dp + ix;
+
+ /* an alias for the digits of b */
+ tmpy = b->dp;
+
+ /* compute the columns of the output and propagate the carry */
+ for (iy = 0; iy < pb; iy++) {
+ /* compute the column as a mp_word */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* the new column is the lower part of the result */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry word from the result */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ /* set carry if it is placed below digs */
+ if (ix + iy < digs) {
+ *tmpt = u;
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, c);
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b. This saves alot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+ int x, bits, res;
+
+ /* how many bits of last digit does b use */
+ bits = mp_count_bits (b) % DIGIT_BIT;
+
+ if (b->used > 1) {
+ if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ mp_set(a, 1);
+ bits = 1;
+ }
+
+
+ /* now compute C = A * B mod b */
+ for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+ if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+ return res;
+ }
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+ return res;
+ }
+ }
+ }
+
+ return MP_OKAY;
+}
+
+
+#ifdef MP_LOW_MEM
+ #define TAB_SIZE 32
+#else
+ #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res, mu;
+ mp_digit buf;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+ int (*redux)(mp_int*,mp_int*,mp_int*);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+#ifdef MP_LOW_MEM
+ if (winsize > 5) {
+ winsize = 5;
+ }
+#endif
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* create mu, used for Barrett reduction */
+ if ((err = mp_init (&mu)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ if (redmode == 0) {
+ if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce;
+ } else {
+ if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce_2k_l;
+ }
+
+ /* create M table
+ *
+ * The M table contains powers of the base,
+ * e.g. M[x] = G**x mod P
+ *
+ * The first half of the table is not
+ * computed though accept for M[0] and M[1]
+ */
+ if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring
+ * M[1] (winsize-1) times
+ */
+ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ /* square it */
+ if ((err = mp_sqr (&M[1 << (winsize - 1)],
+ &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* reduce modulo P */
+ if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+ * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+ */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ mp_set (&res, 1);
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset the bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int) DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ return mp_div (a, b, a, NULL);
+}
+
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+ mp_int q;
+ int res, um = m->used;
+
+ /* q = x */
+ if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+ return res;
+ }
+
+ /* q1 = x / b**(k-1) */
+ mp_rshd (&q, um - 1);
+
+ /* according to HAC this optimization is ok */
+ if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+ if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+ if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+ if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+#else
+ {
+ res = MP_VAL;
+ goto CLEANUP;
+ }
+#endif
+ }
+
+ /* q3 = q2 / b**(k+1) */
+ mp_rshd (&q, um + 1);
+
+ /* x = x mod b**(k+1), quick (no division) */
+ if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* q = q * m mod b**(k+1), quick (no division) */
+ if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* x = x - q */
+ if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* If x < 0, add b**(k+1) to it */
+ if (mp_cmp_d (x, 0) == MP_LT) {
+ mp_set (&q, 1);
+ if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+ goto CLEANUP;
+ if ((res = mp_add (x, &q, x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ /* Back off if it's too big */
+ while (mp_cmp (x, m) != MP_LT) {
+ if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ }
+
+CLEANUP:
+ mp_clear (&q);
+
+ return res;
+}
+
+
+/* reduces a modulo n where n is of the form 2**p - d
+ This differs from reduce_2k since "d" can be larger
+ than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* q = q * d */
+ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+ int res;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear(&tmp);
+ return res;
+}
+
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ if (((a->used + b->used + 1) < MP_WARRAY)
+ && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_high_digs (a, b, c, digs);
+ }
+#endif
+
+ if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ t.used = a->used + b->used + 1;
+
+ pa = a->used;
+ pb = b->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* clear the carry */
+ u = 0;
+
+ /* left hand side of A[ix] * B[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias to the address of where the digits will be stored */
+ tmpt = &(t.dp[digs]);
+
+ /* alias for where to read the right hand side from */
+ tmpy = b->dp + (digs - ix);
+
+ for (iy = digs - ix; iy < pb; iy++) {
+ /* calculate the double precision result */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* get the lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* carry the carry */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ *tmpt = u;
+ }
+ mp_clamp (&t);
+ mp_exch (&t, c);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs. See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed. This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ mp_word _W;
+
+ /* grow the destination as required */
+ pa = a->used + b->used;
+ if (c->alloc < pa) {
+ if ((res = mp_grow (c, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = a->used + b->used;
+ _W = 0;
+ for (ix = digs; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially its
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ register mp_digit *tmpc;
+
+ tmpc = c->dp + digs;
+ for (ix = digs; ix <= pa; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+
+#ifdef CYASSL_KEY_GEN
+
+int mp_cnt_lsb(mp_int *a);
+
+/* c = a * a (mod b) */
+int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, b, c);
+ mp_clear (&t);
+ return res;
+}
+
+
+/* single digit addition */
+int mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ int res, ix, oldused;
+ mp_digit *tmpa, *tmpc, mu;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative and |a| >= b, call c = |a| - b */
+ if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+ /* temporarily fix sign of a */
+ a->sign = MP_ZPOS;
+
+ /* c = |a| - b */
+ res = mp_sub_d(a, b, c);
+
+ /* fix sign */
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* old number of used digits in c */
+ oldused = c->used;
+
+ /* sign always positive */
+ c->sign = MP_ZPOS;
+
+ /* source alias */
+ tmpa = a->dp;
+
+ /* destination alias */
+ tmpc = c->dp;
+
+ /* if a is positive */
+ if (a->sign == MP_ZPOS) {
+ /* add digit, after this we're propagating
+ * the carry.
+ */
+ *tmpc = *tmpa++ + b;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+
+ /* now handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ + mu;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+ }
+ /* set final carry */
+ ix++;
+ *tmpc++ = mu;
+
+ /* setup size */
+ c->used = a->used + 1;
+ } else {
+ /* a was negative and |a| < b */
+ c->used = 1;
+
+ /* the result is a single digit */
+ if (a->used == 1) {
+ *tmpc++ = b - a->dp[0];
+ } else {
+ *tmpc++ = b;
+ }
+
+ /* setup count so the clearing of oldused
+ * can fall through correctly
+ */
+ ix = 1;
+ }
+
+ /* now zero to oldused */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+
+
+/* single digit subtraction */
+int mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit *tmpa, *tmpc, mu;
+ int res, ix, oldused;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative just do an unsigned
+ * addition [with fudged signs]
+ */
+ if (a->sign == MP_NEG) {
+ a->sign = MP_ZPOS;
+ res = mp_add_d(a, b, c);
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* setup regs */
+ oldused = c->used;
+ tmpa = a->dp;
+ tmpc = c->dp;
+
+ /* if a <= b simply fix the single digit */
+ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+ if (a->used == 1) {
+ *tmpc++ = b - *tmpa;
+ } else {
+ *tmpc++ = b;
+ }
+ ix = 1;
+
+ /* negative/1digit */
+ c->sign = MP_NEG;
+ c->used = 1;
+ } else {
+ /* positive/size */
+ c->sign = MP_ZPOS;
+ c->used = a->used;
+
+ /* subtract first digit */
+ *tmpc = *tmpa++ - b;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+
+ /* handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ - mu;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* zero excess digits */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+ return MP_OKAY;
+}
+
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+ int x;
+
+ /* fast return if no power of two */
+ if ((b==0) || (b & (b-1))) {
+ return 0;
+ }
+
+ for (x = 0; x < DIGIT_BIT; x++) {
+ if (b == (((mp_digit)1)<<x)) {
+ *p = x;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w;
+ mp_digit t;
+ int res, ix;
+
+ /* cannot divide by zero */
+ if (b == 0) {
+ return MP_VAL;
+ }
+
+ /* quick outs */
+ if (b == 1 || mp_iszero(a) == 1) {
+ if (d != NULL) {
+ *d = 0;
+ }
+ if (c != NULL) {
+ return mp_copy(a, c);
+ }
+ return MP_OKAY;
+ }
+
+ /* power of two ? */
+ if (s_is_power_of_two(b, &ix) == 1) {
+ if (d != NULL) {
+ *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+ }
+ if (c != NULL) {
+ return mp_div_2d(a, ix, c, NULL);
+ }
+ return MP_OKAY;
+ }
+
+#ifdef BN_MP_DIV_3_C
+ /* three? */
+ if (b == 3) {
+ return mp_div_3(a, c, d);
+ }
+#endif
+
+ /* no easy answer [c'est la vie]. Just division */
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= b) {
+ t = (mp_digit)(w / b);
+ w -= ((mp_word)t) * ((mp_word)b);
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+
+int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+ return mp_div_d(a, b, NULL, c);
+}
+
+
+const mp_digit ltm_prime_tab[] = {
+ 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+ 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+ 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+ 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+ 0x0083,
+ 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+ 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+ 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+ 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+ 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+ 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+ 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+ 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+ 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+ 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+ 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+ 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+ 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+ 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+ 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+ 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+ 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+ 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+ 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+ 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+ 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+ 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+ 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+ 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+ 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+ 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+ 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+ 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+
+
+/* Miller-Rabin test of "a" to the base of "b" as described in
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+ mp_int n1, y, r;
+ int s, j, err;
+
+ /* default */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* get n1 = a - 1 */
+ if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* set 2**s * r = n1 */
+ if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* count the number of least significant bits
+ * which are zero
+ */
+ s = mp_cnt_lsb(&r);
+
+ /* now divide n - 1 by 2**s */
+ if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+ goto LBL_R;
+ }
+
+ /* compute y = b**r mod a */
+ if ((err = mp_init (&y)) != MP_OKAY) {
+ goto LBL_R;
+ }
+ if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y != 1 and y != n1 do */
+ if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+ j = 1;
+ /* while j <= s-1 and y != n1 */
+ while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+ if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y == 1 then composite */
+ if (mp_cmp_d (&y, 1) == MP_EQ) {
+ goto LBL_Y;
+ }
+
+ ++j;
+ }
+
+ /* if y != n1 then composite */
+ if (mp_cmp (&y, &n1) != MP_EQ) {
+ goto LBL_Y;
+ }
+ }
+
+ /* probably prime now */
+ *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+ return err;
+}
+
+
+/* determines if an integers is divisible by one
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+int mp_prime_is_divisible (mp_int * a, int *result)
+{
+ int err, ix;
+ mp_digit res;
+
+ /* default to not */
+ *result = MP_NO;
+
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ /* what is a mod LBL_prime_tab[ix] */
+ if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* is the residue zero? */
+ if (res == 0) {
+ *result = MP_YES;
+ return MP_OKAY;
+ }
+ }
+
+ return MP_OKAY;
+}
+
+
+/*
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+ mp_int b;
+ int ix, err, res;
+
+ /* default to no */
+ *result = MP_NO;
+
+ /* valid value of t? */
+ if (t <= 0 || t > PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* is the input equal to one of the primes in the table? */
+ for (ix = 0; ix < PRIME_SIZE; ix++) {
+ if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+ *result = 1;
+ return MP_OKAY;
+ }
+ }
+
+ /* first perform trial division */
+ if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* return if it was trivially divisible */
+ if (res == MP_YES) {
+ return MP_OKAY;
+ }
+
+ /* now perform the miller-rabin rounds */
+ if ((err = mp_init (&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (ix = 0; ix < t; ix++) {
+ /* set the prime */
+ mp_set (&b, ltm_prime_tab[ix]);
+
+ if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+ goto LBL_B;
+ }
+
+ if (res == MP_NO) {
+ goto LBL_B;
+ }
+ }
+
+ /* passed the test */
+ *result = MP_YES;
+LBL_B:mp_clear (&b);
+ return err;
+}
+
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t1, t2;
+
+
+ if ((res = mp_init_multi (&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* t1 = get the GCD of the two inputs */
+ if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+ goto LBL_T;
+ }
+
+ /* divide the smallest by the GCD */
+ if (mp_cmp_mag(a, b) == MP_LT) {
+ /* store quotient in t2 such that t2 * b is the LCM */
+ if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(b, &t2, c);
+ } else {
+ /* store quotient in t2 such that t2 * a is the LCM */
+ if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+ goto LBL_T;
+ }
+ res = mp_mul(a, &t2, c);
+ }
+
+ /* fix the sign to positive */
+ c->sign = MP_ZPOS;
+
+LBL_T:
+ mp_clear(&t1);
+ mp_clear(&t2);
+ return res;
+}
+
+
+static const int lnz[16] = {
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+ int x;
+ mp_digit q, qq;
+
+ /* easy out */
+ if (mp_iszero(a) == 1) {
+ return 0;
+ }
+
+ /* scan lower digits until non-zero */
+ for (x = 0; x < a->used && a->dp[x] == 0; x++);
+ q = a->dp[x];
+ x *= DIGIT_BIT;
+
+ /* now scan this digit until a 1 is found */
+ if ((q & 1) == 0) {
+ do {
+ qq = q & 15;
+ x += lnz[qq];
+ q >>= 4;
+ } while (qq == 0);
+ }
+ return x;
+}
+
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int u, v;
+ int k, u_lsb, v_lsb, res;
+
+ /* either zero than gcd is the largest */
+ if (mp_iszero (a) == MP_YES) {
+ return mp_abs (b, c);
+ }
+ if (mp_iszero (b) == MP_YES) {
+ return mp_abs (a, c);
+ }
+
+ /* get copies of a and b we can modify */
+ if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+ goto LBL_U;
+ }
+
+ /* must be positive for the remainder of the algorithm */
+ u.sign = v.sign = MP_ZPOS;
+
+ /* B1. Find the common power of two for u and v */
+ u_lsb = mp_cnt_lsb(&u);
+ v_lsb = mp_cnt_lsb(&v);
+ k = MIN(u_lsb, v_lsb);
+
+ if (k > 0) {
+ /* divide the power of two out */
+ if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* divide any remaining factors of two out */
+ if (u_lsb != k) {
+ if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ if (v_lsb != k) {
+ if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ while (mp_iszero(&v) == 0) {
+ /* make sure v is the largest */
+ if (mp_cmp_mag(&u, &v) == MP_GT) {
+ /* swap u and v to make sure v is >= u */
+ mp_exch(&u, &v);
+ }
+
+ /* subtract smallest from largest */
+ if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+ goto LBL_V;
+ }
+
+ /* Divide out all factors of two */
+ if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ }
+
+ /* multiply by 2**k which we divided out at the beginning */
+ if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+ goto LBL_V;
+ }
+ c->sign = MP_ZPOS;
+ res = MP_OKAY;
+LBL_V:mp_clear (&u);
+LBL_U:mp_clear (&v);
+ return res;
+}
+
+
+/* set a 32-bit const */
+int mp_set_int (mp_int * a, unsigned long b)
+{
+ int x, res;
+
+ mp_zero (a);
+
+ /* set four bits at a time */
+ for (x = 0; x < 8; x++) {
+ /* shift the number up four bits */
+ if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* OR in the top four bits of the source */
+ a->dp[0] |= (b >> 28) & 15;
+
+ /* shift the source up to the next four bits */
+ b <<= 4;
+
+ /* ensure that digits are not clamped off */
+ a->used += 1;
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+
+
+#endif /* CYASSL_KEY_GEN */
+
+#endif /* USE_FAST_MATH */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/integer.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,325 @@
+/* integer.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+/*
+ * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca,
+ * http://math.libtomcrypt.com
+ */
+
+
+#ifndef CTAO_CRYPT_INTEGER_H
+#define CTAO_CRYPT_INTEGER_H
+
+/* may optionally use fast math instead, not yet supported on all platforms and
+ may not be faster on all
+*/
+#include "types.h"
+#ifdef USE_FAST_MATH
+ #include "tfm.h"
+#else
+
+#ifndef CHAR_BIT
+ #include <limits.h>
+#endif
+
+#include "types.h" /* will set MP_xxBIT if not default */
+#include "mpi_class.h"
+
+#ifndef MIN
+ #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+ #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#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
+
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__)
+ #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+ #define MP_64BIT
+ #endif
+#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 unsigned long 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 test macro */
+ #define DIGIT_BIT 28
+ #define MP_28BIT
+#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_ON 0x0008 /* force 2nd MSB to 1 */
+
+typedef int mp_err;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+#define MP_LOW_MEM
+
+/* default precision */
+#ifndef MP_PREC
+ #ifndef MP_LOW_MEM
+ #define MP_PREC 32 /* default digits of precision */
+ #else
+ #define MP_PREC 1 /* 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)
+
+
+/* ---> 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)
+
+
+/* number of primes */
+#ifdef MP_8BIT
+ #define PRIME_SIZE 31
+#else
+ #define PRIME_SIZE 256
+#endif
+
+#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)
+
+#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)
+
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+
+extern const char *mp_s_rmap;
+
+/* 6 functions needed by Rsa */
+int mp_init (mp_int * a);
+void mp_clear (mp_int * a);
+int mp_unsigned_bin_size(mp_int * a);
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b);
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
+/* end functions needed by Rsa */
+
+/* functions added to support above needed, removed TOOM and KARATSUBA */
+int mp_count_bits (mp_int * a);
+int mp_init_copy (mp_int * a, mp_int * b);
+int mp_copy (mp_int * a, mp_int * b);
+int mp_grow (mp_int * a, int size);
+void bn_reverse (unsigned char *s, int len);
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d);
+void mp_zero (mp_int * a);
+void mp_clamp (mp_int * a);
+void mp_exch (mp_int * a, mp_int * b);
+void mp_rshd (mp_int * a, int b);
+int mp_mod_2d (mp_int * a, int b, mp_int * c);
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
+int mp_mul_2d (mp_int * a, int b, mp_int * c);
+int mp_lshd (mp_int * a, int b);
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
+int mp_abs (mp_int * a, mp_int * b);
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c);
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c);
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+int mp_cmp_mag (mp_int * a, mp_int * b);
+int mp_cmp (mp_int * a, mp_int * b);
+int mp_cmp_d(mp_int * a, mp_digit b);
+void mp_set (mp_int * a, mp_digit b);
+int mp_mod (mp_int * a, mp_int * b, mp_int * c);
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+int mp_div_2(mp_int * a, mp_int * b);
+int mp_add (mp_int * a, mp_int * b, mp_int * c);
+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);
+int mp_sub (mp_int * a, mp_int * b, mp_int * c);
+int mp_init (mp_int * a);
+int mp_reduce_is_2k_l(mp_int *a);
+int mp_reduce_is_2k(mp_int *a);
+int mp_dr_is_modulus(mp_int *a);
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int);
+int mp_montgomery_setup (mp_int * n, mp_digit * rho);
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho);
+int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho);
+void mp_dr_setup(mp_int *a, mp_digit *d);
+int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k);
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+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 mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu);
+int mp_reduce_setup (mp_int * a, mp_int * b);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b);
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+int s_mp_sqr (mp_int * a, mp_int * b);
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+int fast_s_mp_sqr (mp_int * a, mp_int * b);
+int mp_init_size (mp_int * a, int size);
+int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d);
+int mp_mul_2(mp_int * a, mp_int * b);
+int mp_mul (mp_int * a, mp_int * b, mp_int * c);
+int mp_sqr (mp_int * a, mp_int * b);
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+int mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
+int mp_2expt (mp_int * a, int b);
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+/* end support added functions */
+
+/* added */
+int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
+ mp_int* f);
+
+#ifdef CYASSL_KEY_GEN
+ int mp_prime_is_prime (mp_int * a, int t, int *result);
+ int mp_set_int (mp_int * a, unsigned long b);
+ int mp_gcd (mp_int * a, mp_int * b, mp_int * c);
+ int mp_lcm (mp_int * a, mp_int * b, mp_int * c);
+ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c);
+#endif
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* USE_FAST_MATH */
+
+#endif /* CTAO_CRYPT_INTEGER_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/keys.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,613 @@
+/* keys.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#ifdef SHOW_SECRETS
+ #include <stdio.h>
+#endif
+
+
+#ifndef NO_TLS
+ int MakeTlsMasterSecret(SSL*);
+ void TLS_hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify);
+#endif
+
+
+
+int SetCipherSpecs(SSL* ssl)
+{
+ switch (ssl->options.cipherSuite) {
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
+ case SSL_RSA_WITH_RC4_128_SHA :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA
+ case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5
+ case SSL_RSA_WITH_RC4_128_MD5 :
+ ssl->specs.bulk_cipher_algorithm = rc4;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = md5_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = MD5_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_MD5;
+ ssl->specs.key_size = RC4_KEY_SIZE;
+ ssl->specs.iv_size = 0;
+ ssl->specs.block_size = 0;
+
+ break;
+#endif
+
+#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = triple_des;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = DES3_KEY_SIZE;
+ ssl->specs.block_size = DES_BLOCK_SIZE;
+ ssl->specs.iv_size = DES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA
+ case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = triple_des;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = DES3_KEY_SIZE;
+ ssl->specs.block_size = DES_BLOCK_SIZE;
+ ssl->specs.iv_size = DES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA
+ case TLS_RSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA
+ case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA
+ case TLS_RSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA
+ case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = ntru_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA
+ case TLS_PSK_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = psk_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ ssl->options.usingPSK_cipher = 1;
+ break;
+#endif
+
+#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA
+ case TLS_PSK_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = psk_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ ssl->options.usingPSK_cipher = 1;
+ break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_128_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = aes;
+ ssl->specs.cipher_type = block;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = diffie_hellman_kea;
+ ssl->specs.sig_algo = rsa_sa_algo;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = AES_256_KEY_SIZE;
+ ssl->specs.block_size = AES_BLOCK_SIZE;
+ ssl->specs.iv_size = AES_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5
+ case TLS_RSA_WITH_HC_128_CBC_MD5 :
+ ssl->specs.bulk_cipher_algorithm = hc128;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = md5_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = MD5_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_MD5;
+ ssl->specs.key_size = HC_128_KEY_SIZE;
+ ssl->specs.block_size = 0;
+ ssl->specs.iv_size = HC_128_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA
+ case TLS_RSA_WITH_HC_128_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = hc128;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = HC_128_KEY_SIZE;
+ ssl->specs.block_size = 0;
+ ssl->specs.iv_size = HC_128_IV_SIZE;
+
+ break;
+#endif
+
+#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA
+ case TLS_RSA_WITH_RABBIT_CBC_SHA :
+ ssl->specs.bulk_cipher_algorithm = rabbit;
+ ssl->specs.cipher_type = stream;
+ ssl->specs.mac_algorithm = sha_mac;
+ ssl->specs.kea = rsa_kea;
+ ssl->specs.hash_size = SHA_DIGEST_SIZE;
+ ssl->specs.pad_size = PAD_SHA;
+ ssl->specs.key_size = RABBIT_KEY_SIZE;
+ ssl->specs.block_size = 0;
+ ssl->specs.iv_size = RABBIT_IV_SIZE;
+
+ break;
+#endif
+
+ default:
+ return UNSUPPORTED_SUITE;
+ }
+
+ /* set TLS if it hasn't been turned off */
+ if (ssl->version.major == 3 && ssl->version.minor >= 1) {
+#ifndef NO_TLS
+ ssl->options.tls = 1;
+ ssl->hmac = TLS_hmac;
+ if (ssl->version.minor == 2)
+ ssl->options.tls1_1 = 1;
+#endif
+ }
+
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ ssl->hmac = TLS_hmac;
+#endif
+
+ return 0;
+}
+
+
+enum KeyStuff {
+ MASTER_ROUNDS = 3,
+ PREFIX = 3, /* up to three letters for master prefix */
+ KEY_PREFIX = 7 /* up to 7 prefix letters for key rounds */
+
+
+};
+
+
+/* true or false, zero for error */
+static int SetPrefix(byte* sha_input, int index)
+{
+ switch (index) {
+ case 0:
+ XMEMCPY(sha_input, "A", 1);
+ break;
+ case 1:
+ XMEMCPY(sha_input, "BB", 2);
+ break;
+ case 2:
+ XMEMCPY(sha_input, "CCC", 3);
+ break;
+ case 3:
+ XMEMCPY(sha_input, "DDDD", 4);
+ break;
+ case 4:
+ XMEMCPY(sha_input, "EEEEE", 5);
+ break;
+ case 5:
+ XMEMCPY(sha_input, "FFFFFF", 6);
+ break;
+ case 6:
+ XMEMCPY(sha_input, "GGGGGGG", 7);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+
+static int SetKeys(Ciphers* encrypt, Ciphers* decrypt, Keys* keys,
+ CipherSpecs* specs, byte side)
+{
+#ifdef BUILD_ARC4
+ word32 sz = specs->key_size;
+ if (specs->bulk_cipher_algorithm == rc4) {
+ if (side == CLIENT_END) {
+ Arc4SetKey(&encrypt->arc4, keys->client_write_key, sz);
+ Arc4SetKey(&decrypt->arc4, keys->server_write_key, sz);
+ }
+ else {
+ Arc4SetKey(&encrypt->arc4, keys->server_write_key, sz);
+ Arc4SetKey(&decrypt->arc4, keys->client_write_key, sz);
+ }
+ }
+#endif
+
+#ifdef BUILD_HC128
+ if (specs->bulk_cipher_algorithm == hc128) {
+ if (side == CLIENT_END) {
+ Hc128_SetKey(&encrypt->hc128, keys->client_write_key,
+ keys->client_write_IV);
+ Hc128_SetKey(&decrypt->hc128, keys->server_write_key,
+ keys->server_write_IV);
+ }
+ else {
+ Hc128_SetKey(&encrypt->hc128, keys->server_write_key,
+ keys->server_write_IV);
+ Hc128_SetKey(&decrypt->hc128, keys->client_write_key,
+ keys->client_write_IV);
+ }
+ }
+#endif
+
+#ifdef BUILD_RABBIT
+ if (specs->bulk_cipher_algorithm == rabbit) {
+ if (side == CLIENT_END) {
+ RabbitSetKey(&encrypt->rabbit, keys->client_write_key,
+ keys->client_write_IV);
+ RabbitSetKey(&decrypt->rabbit, keys->server_write_key,
+ keys->server_write_IV);
+ }
+ else {
+ RabbitSetKey(&encrypt->rabbit, keys->server_write_key,
+ keys->server_write_IV);
+ RabbitSetKey(&decrypt->rabbit, keys->client_write_key,
+ keys->client_write_IV);
+ }
+ }
+#endif
+
+#ifdef BUILD_DES3
+ if (specs->bulk_cipher_algorithm == triple_des) {
+ if (side == CLIENT_END) {
+ Des3_SetKey(&encrypt->des3, keys->client_write_key,
+ keys->client_write_IV, DES_ENCRYPTION);
+ Des3_SetKey(&decrypt->des3, keys->server_write_key,
+ keys->server_write_IV, DES_DECRYPTION);
+ }
+ else {
+ Des3_SetKey(&encrypt->des3, keys->server_write_key,
+ keys->server_write_IV, DES_ENCRYPTION);
+ Des3_SetKey(&decrypt->des3, keys->client_write_key,
+ keys->client_write_IV, DES_DECRYPTION);
+ }
+ }
+#endif
+
+#ifdef BUILD_AES
+ if (specs->bulk_cipher_algorithm == aes) {
+ if (side == CLIENT_END) {
+ AesSetKey(&encrypt->aes, keys->client_write_key,
+ specs->key_size, keys->client_write_IV,
+ AES_ENCRYPTION);
+ AesSetKey(&decrypt->aes, keys->server_write_key,
+ specs->key_size, keys->server_write_IV,
+ AES_DECRYPTION);
+ }
+ else {
+ AesSetKey(&encrypt->aes, keys->server_write_key,
+ specs->key_size, keys->server_write_IV,
+ AES_ENCRYPTION);
+ AesSetKey(&decrypt->aes, keys->client_write_key,
+ specs->key_size, keys->client_write_IV,
+ AES_DECRYPTION);
+ }
+ }
+#endif
+
+ keys->sequence_number = 0;
+ keys->peer_sequence_number = 0;
+ keys->encryptionOn = 0;
+
+ return 0;
+}
+
+
+/* TLS can call too */
+int StoreKeys(SSL* ssl, const byte* keyData)
+{
+ int sz = ssl->specs.hash_size, i;
+
+ XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz);
+ i = sz;
+ XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz);
+ i += sz;
+
+ sz = ssl->specs.key_size;
+ XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz);
+ i += sz;
+ XMEMCPY(ssl->keys.server_write_key, &keyData[i], sz);
+ i += sz;
+
+ sz = ssl->specs.iv_size;
+ XMEMCPY(ssl->keys.client_write_IV, &keyData[i], sz);
+ i += sz;
+ XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz);
+
+ return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs,
+ ssl->options.side);
+}
+
+
+int DeriveKeys(SSL* ssl)
+{
+ int length = 2 * ssl->specs.hash_size +
+ 2 * ssl->specs.key_size +
+ 2 * ssl->specs.iv_size;
+ int rounds = (length + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i;
+
+ byte shaOutput[SHA_DIGEST_SIZE];
+ byte md5Input[SECRET_LEN + SHA_DIGEST_SIZE];
+ byte shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
+
+ Md5 md5;
+ Sha sha;
+
+ byte keyData[KEY_PREFIX * MD5_DIGEST_SIZE]; /* max size */
+
+ InitMd5(&md5);
+ InitSha(&sha);
+
+ XMEMCPY(md5Input, ssl->arrays.masterSecret, SECRET_LEN);
+
+ for (i = 0; i < rounds; ++i) {
+ int j = i + 1;
+ int idx = j;
+
+ if (!SetPrefix(shaInput, i)) {
+ return PREFIX_ERROR;
+ }
+
+ XMEMCPY(shaInput + idx, ssl->arrays.masterSecret, SECRET_LEN);
+ idx += SECRET_LEN;
+ XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN);
+ idx += RAN_LEN;
+ XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN);
+ idx += RAN_LEN;
+
+ ShaUpdate(&sha, shaInput, sizeof(shaInput) - KEY_PREFIX + j);
+ ShaFinal(&sha, shaOutput);
+
+ XMEMCPY(&md5Input[SECRET_LEN], shaOutput, SHA_DIGEST_SIZE);
+ Md5Update(&md5, md5Input, sizeof(md5Input));
+ Md5Final(&md5, keyData + i * MD5_DIGEST_SIZE);
+ }
+
+ return StoreKeys(ssl, keyData);
+}
+
+
+void CleanPreMaster(SSL* ssl)
+{
+ int i, sz = ssl->arrays.preMasterSz;
+
+ for (i = 0; i < sz; i++)
+ ssl->arrays.preMasterSecret[i] = 0;
+
+ RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret, sz);
+
+ for (i = 0; i < sz; i++)
+ ssl->arrays.preMasterSecret[i] = 0;
+
+}
+
+
+/* Create and store the master secret see page 32, 6.1 */
+int MakeMasterSecret(SSL* ssl)
+{
+ byte shaOutput[SHA_DIGEST_SIZE];
+ byte md5Input[ENCRYPT_LEN + SHA_DIGEST_SIZE];
+ byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN];
+ int i;
+ word32 idx;
+ word32 pmsSz = ssl->arrays.preMasterSz;
+
+ Md5 md5;
+ Sha sha;
+
+#ifdef SHOW_SECRETS
+ {
+ int j;
+ printf("pre master secret: ");
+ for (j = 0; j < pmsSz; j++)
+ printf("%02x", ssl->arrays.preMasterSecret[j]);
+ printf("\n");
+ }
+#endif
+
+#ifndef NO_TLS
+ if (ssl->options.tls) return MakeTlsMasterSecret(ssl);
+#endif
+
+ InitMd5(&md5);
+ InitSha(&sha);
+
+ XMEMCPY(md5Input, ssl->arrays.preMasterSecret, pmsSz);
+
+ for (i = 0; i < MASTER_ROUNDS; ++i) {
+ byte prefix[PREFIX];
+ if (!SetPrefix(prefix, i)) {
+ return PREFIX_ERROR;
+ }
+
+ idx = 0;
+ XMEMCPY(shaInput, prefix, i + 1);
+ idx += i + 1;
+
+ XMEMCPY(shaInput + idx, ssl->arrays.preMasterSecret, pmsSz);
+ idx += pmsSz;
+ XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN);
+ idx += RAN_LEN;
+ XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN);
+ idx += RAN_LEN;
+ ShaUpdate(&sha, shaInput, idx);
+ ShaFinal(&sha, shaOutput);
+
+ idx = pmsSz; /* preSz */
+ XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE);
+ idx += SHA_DIGEST_SIZE;
+ Md5Update(&md5, md5Input, idx);
+ Md5Final(&md5, &ssl->arrays.masterSecret[i * MD5_DIGEST_SIZE]);
+ }
+
+#ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("master secret: ");
+ for (i = 0; i < SECRET_LEN; i++)
+ printf("%02x", ssl->arrays.masterSecret[i]);
+ printf("\n");
+ }
+#endif
+
+ DeriveKeys(ssl);
+ CleanPreMaster(ssl);
+
+ return 0;
+}
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/md4.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,215 @@
+/* md4.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_MD4
+
+#include "ctc_md4.h"
+#ifdef NO_INLINE
+ #include "misc.h"
+#else
+ #include "misc.c"
+#endif
+
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+void InitMd4(Md4* md4)
+{
+ md4->digest[0] = 0x67452301L;
+ md4->digest[1] = 0xefcdab89L;
+ md4->digest[2] = 0x98badcfeL;
+ md4->digest[3] = 0x10325476L;
+
+ md4->buffLen = 0;
+ md4->loLen = 0;
+ md4->hiLen = 0;
+}
+
+
+static void Transform(Md4* md4)
+{
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+ /* Copy context->state[] to working vars */
+ word32 A = md4->digest[0];
+ word32 B = md4->digest[1];
+ word32 C = md4->digest[2];
+ word32 D = md4->digest[3];
+
+#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+md4->buffer[k],s);
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 1, 7);
+ function(C,D,A,B, 2,11);
+ function(B,C,D,A, 3,19);
+ function(A,B,C,D, 4, 3);
+ function(D,A,B,C, 5, 7);
+ function(C,D,A,B, 6,11);
+ function(B,C,D,A, 7,19);
+ function(A,B,C,D, 8, 3);
+ function(D,A,B,C, 9, 7);
+ function(C,D,A,B,10,11);
+ function(B,C,D,A,11,19);
+ function(A,B,C,D,12, 3);
+ function(D,A,B,C,13, 7);
+ function(C,D,A,B,14,11);
+ function(B,C,D,A,15,19);
+
+#undef function
+#define function(a,b,c,d,k,s) \
+ a=rotlFixed(a+G(b,c,d)+md4->buffer[k]+0x5a827999,s);
+
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 4, 5);
+ function(C,D,A,B, 8, 9);
+ function(B,C,D,A,12,13);
+ function(A,B,C,D, 1, 3);
+ function(D,A,B,C, 5, 5);
+ function(C,D,A,B, 9, 9);
+ function(B,C,D,A,13,13);
+ function(A,B,C,D, 2, 3);
+ function(D,A,B,C, 6, 5);
+ function(C,D,A,B,10, 9);
+ function(B,C,D,A,14,13);
+ function(A,B,C,D, 3, 3);
+ function(D,A,B,C, 7, 5);
+ function(C,D,A,B,11, 9);
+ function(B,C,D,A,15,13);
+
+#undef function
+#define function(a,b,c,d,k,s) \
+ a=rotlFixed(a+H(b,c,d)+md4->buffer[k]+0x6ed9eba1,s);
+
+ function(A,B,C,D, 0, 3);
+ function(D,A,B,C, 8, 9);
+ function(C,D,A,B, 4,11);
+ function(B,C,D,A,12,15);
+ function(A,B,C,D, 2, 3);
+ function(D,A,B,C,10, 9);
+ function(C,D,A,B, 6,11);
+ function(B,C,D,A,14,15);
+ function(A,B,C,D, 1, 3);
+ function(D,A,B,C, 9, 9);
+ function(C,D,A,B, 5,11);
+ function(B,C,D,A,13,15);
+ function(A,B,C,D, 3, 3);
+ function(D,A,B,C,11, 9);
+ function(C,D,A,B, 7,11);
+ function(B,C,D,A,15,15);
+
+ /* Add the working vars back into digest state[] */
+ md4->digest[0] += A;
+ md4->digest[1] += B;
+ md4->digest[2] += C;
+ md4->digest[3] += D;
+}
+
+
+static INLINE void AddLength(Md4* md4, word32 len)
+{
+ word32 tmp = md4->loLen;
+ if ( (md4->loLen += len) < tmp)
+ md4->hiLen++; /* carry low to high */
+}
+
+
+void Md4Update(Md4* md4, const byte* data, word32 len)
+{
+ /* do block size increments */
+ byte* local = (byte*)md4->buffer;
+
+ while (len) {
+ word32 add = min(len, MD4_BLOCK_SIZE - md4->buffLen);
+ XMEMCPY(&local[md4->buffLen], data, add);
+
+ md4->buffLen += add;
+ data += add;
+ len -= add;
+
+ if (md4->buffLen == MD4_BLOCK_SIZE) {
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseBytes(local, local, MD4_BLOCK_SIZE);
+ #endif
+ Transform(md4);
+ AddLength(md4, MD4_BLOCK_SIZE);
+ md4->buffLen = 0;
+ }
+ }
+}
+
+
+void Md4Final(Md4* md4, byte* hash)
+{
+ byte* local = (byte*)md4->buffer;
+
+ AddLength(md4, md4->buffLen); /* before adding pads */
+
+ local[md4->buffLen++] = 0x80; /* add 1 */
+
+ /* pad with zeros */
+ if (md4->buffLen > MD4_PAD_SIZE) {
+ XMEMSET(&local[md4->buffLen], 0, MD4_BLOCK_SIZE - md4->buffLen);
+ md4->buffLen += MD4_BLOCK_SIZE - md4->buffLen;
+
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseBytes(local, local, MD4_BLOCK_SIZE);
+ #endif
+ Transform(md4);
+ md4->buffLen = 0;
+ }
+ XMEMSET(&local[md4->buffLen], 0, MD4_PAD_SIZE - md4->buffLen);
+
+ /* put lengths in bits */
+ md4->loLen = md4->loLen << 3;
+ md4->hiLen = (md4->loLen >> (8*sizeof(md4->loLen) - 3)) +
+ (md4->hiLen << 3);
+
+ /* store lengths */
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseBytes(local, local, MD4_BLOCK_SIZE);
+ #endif
+ /* ! length ordering dependent on digest endian type ! */
+ XMEMCPY(&local[MD4_PAD_SIZE], &md4->loLen, sizeof(word32));
+ XMEMCPY(&local[MD4_PAD_SIZE + sizeof(word32)], &md4->hiLen, sizeof(word32));
+
+ Transform(md4);
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseWords(md4->digest, md4->digest, MD4_DIGEST_SIZE);
+ #endif
+ XMEMCPY(hash, md4->digest, MD4_DIGEST_SIZE);
+
+ InitMd4(md4); /* reset state */
+}
+
+
+#endif /* NO_MD4 */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/md5.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,222 @@
+/* md5.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "ctc_md5.h"
+#ifdef NO_INLINE
+ #include "misc.h"
+#else
+ #include "misc.c"
+#endif
+
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+void InitMd5(Md5* md5)
+{
+ md5->digest[0] = 0x67452301L;
+ md5->digest[1] = 0xefcdab89L;
+ md5->digest[2] = 0x98badcfeL;
+ md5->digest[3] = 0x10325476L;
+
+ md5->buffLen = 0;
+ md5->loLen = 0;
+ md5->hiLen = 0;
+}
+
+
+static void Transform(Md5* md5)
+{
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+ w = rotlFixed(w + f(x, y, z) + data, s) + x
+
+ /* Copy context->state[] to working vars */
+ word32 a = md5->digest[0];
+ word32 b = md5->digest[1];
+ word32 c = md5->digest[2];
+ word32 d = md5->digest[3];
+
+ MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21);
+
+ /* Add the working vars back into digest state[] */
+ md5->digest[0] += a;
+ md5->digest[1] += b;
+ md5->digest[2] += c;
+ md5->digest[3] += d;
+}
+
+
+static INLINE void AddLength(Md5* md5, word32 len)
+{
+ word32 tmp = md5->loLen;
+ if ( (md5->loLen += len) < tmp)
+ md5->hiLen++; /* carry low to high */
+}
+
+
+void Md5Update(Md5* md5, const byte* data, word32 len)
+{
+ /* do block size increments */
+ byte* local = (byte*)md5->buffer;
+
+ while (len) {
+ word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen);
+ XMEMCPY(&local[md5->buffLen], data, add);
+
+ md5->buffLen += add;
+ data += add;
+ len -= add;
+
+ if (md5->buffLen == MD5_BLOCK_SIZE) {
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseBytes(local, local, MD5_BLOCK_SIZE);
+ #endif
+ Transform(md5);
+ AddLength(md5, MD5_BLOCK_SIZE);
+ md5->buffLen = 0;
+ }
+ }
+}
+
+
+void Md5Final(Md5* md5, byte* hash)
+{
+ byte* local = (byte*)md5->buffer;
+
+ AddLength(md5, md5->buffLen); /* before adding pads */
+
+ local[md5->buffLen++] = 0x80; /* add 1 */
+
+ /* pad with zeros */
+ if (md5->buffLen > MD5_PAD_SIZE) {
+ XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen);
+ md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen;
+
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseBytes(local, local, MD5_BLOCK_SIZE);
+ #endif
+ Transform(md5);
+ md5->buffLen = 0;
+ }
+ XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen);
+
+ /* put lengths in bits */
+ md5->loLen = md5->loLen << 3;
+ md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) +
+ (md5->hiLen << 3);
+
+ /* store lengths */
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseBytes(local, local, MD5_BLOCK_SIZE);
+ #endif
+ /* ! length ordering dependent on digest endian type ! */
+ XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32));
+ XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32));
+
+ Transform(md5);
+ #ifdef BIG_ENDIAN_ORDER
+ ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE);
+ #endif
+ XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE);
+
+ InitMd5(md5); /* reset state */
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,171 @@
+/* misc.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "misc.h"
+
+/* inlining these functions is a huge speed increase and a small size decrease,
+ because the functions are smaller than function call setup/cleanup, e.g.,
+ md5 benchmark is twice as fast with inline. If you don't want it, then
+ define NO_INLINE and compile this file into cyassl, otherwise it's used as
+ a source header
+ */
+
+#ifdef NO_INLINE
+ #define STATIC
+#else
+ #define STATIC static
+#endif
+
+
+#ifdef INTEL_INTRINSICS
+
+ #include <stdlib.h> /* get intrinsic definitions */
+
+ #pragma intrinsic(_lrotl, _lrotr)
+
+ STATIC INLINE word32 rotlFixed(word32 x, word32 y)
+ {
+ return y ? _lrotl(x, y) : x;
+ }
+
+ STATIC INLINE word32 rotrFixed(word32 x, word32 y)
+ {
+ return y ? _lrotr(x, y) : x;
+ }
+
+#else /* generic */
+
+ STATIC INLINE word32 rotlFixed(word32 x, word32 y)
+ {
+ return (x << y) | (x >> (sizeof(y) * 8 - y));
+ }
+
+
+ STATIC INLINE word32 rotrFixed(word32 x, word32 y)
+ {
+ return (x >> y) | (x << (sizeof(y) * 8 - y));
+ }
+
+#endif
+
+
+STATIC INLINE word32 ByteReverseWord32(word32 value)
+{
+#ifdef PPC_INTRINSICS
+ /* PPC: load reverse indexed instruction */
+ return (word32)__lwbrx(&value,0);
+#elif defined(FAST_ROTATE)
+ /* 5 instructions with rotate instruction, 9 without */
+ return (rotrFixed(value, 8U) & 0xff00ff00) |
+ (rotlFixed(value, 8U) & 0x00ff00ff);
+#else
+ /* 6 instructions with rotate instruction, 8 without */
+ value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+ return rotlFixed(value, 16U);
+#endif
+}
+
+
+STATIC INLINE void ByteReverseWords(word32* out, const word32* in,
+ word32 byteCount)
+{
+ word32 count = byteCount/sizeof(word32), i;
+
+ for (i = 0; i < count; i++)
+ out[i] = ByteReverseWord32(in[i]);
+
+}
+
+
+#ifdef WORD64_AVAILABLE
+
+
+STATIC INLINE word64 rotlFixed64(word64 x, word64 y)
+{
+ return (x << y) | (x >> (sizeof(y) * 8 - y));
+}
+
+
+STATIC INLINE word64 rotrFixed64(word64 x, word64 y)
+{
+ return (x >> y) | (x << (sizeof(y) * 8 - y));
+}
+
+
+STATIC INLINE word64 ByteReverseWord64(word64 value)
+{
+#ifdef CTAOCRYPT_SLOW_WORD64
+ return (word64)(ByteReverseWord32((word32)value)) << 32 |
+ ByteReverseWord32((word32)(value>>32));
+#else
+ value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) |
+ ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
+ value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) |
+ ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
+ return rotlFixed64(value, 32U);
+#endif
+}
+
+
+STATIC INLINE void ByteReverseWords64(word64* out, const word64* in,
+ word32 byteCount)
+{
+ word32 count = byteCount/sizeof(word64), i;
+
+ for (i = 0; i < count; i++)
+ out[i] = ByteReverseWord64(in[i]);
+
+}
+
+#endif /* WORD64_AVAILABLE */
+
+
+STATIC INLINE void ByteReverseBytes(byte* out, const byte* in, word32 byteCount)
+{
+ word32* op = (word32*)out;
+ const word32* ip = (const word32*)in;
+
+ ByteReverseWords(op, ip, byteCount);
+}
+
+
+STATIC INLINE void XorWords(word* r, const word* a, word32 n)
+{
+ word32 i;
+
+ for (i = 0; i < n; i++) r[i] ^= a[i];
+}
+
+
+STATIC INLINE void xorbuf(byte* buf, const byte* mask, word32 count)
+{
+ if (((size_t)buf | (size_t)mask | count) % WORD_SIZE == 0)
+ XorWords( (word*)buf, (const word*)mask, count / WORD_SIZE);
+ else {
+ word32 i;
+ for (i = 0; i < count; i++) buf[i] ^= mask[i];
+ }
+}
+
+
+#undef STATIC
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/misc.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,55 @@
+/* misc.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_MISC_H
+#define CTAO_CRYPT_MISC_H
+
+
+#include "types.h"
+
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#ifdef NO_INLINE
+word32 rotlFixed(word32, word32);
+word32 rotrFixed(word32, word32);
+
+word32 ByteReverseWord32(word32);
+void ByteReverseWords(word32*, const word32*, word32);
+void ByteReverseBytes(byte*, const byte*, word32);
+
+void XorWords(word*, const word*, word32);
+void xorbuf(byte*, const byte*, word32);
+#endif /* NO_INLINE */
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* CTAO_CRYPT_MISC_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpi_class.h Sat Feb 05 01:09:17 2011 +0000 @@ -0,0 +1,996 @@ +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#if defined(LTM2) +#define LTM3 +#endif +#if defined(LTM1) +#define LTM2 +#endif +#define LTM1 + +#if defined(LTM_ALL) +#define BN_ERROR_C +#define BN_FAST_MP_INVMOD_C +#define BN_FAST_MP_MONTGOMERY_REDUCE_C +#define BN_FAST_S_MP_MUL_DIGS_C +#define BN_FAST_S_MP_MUL_HIGH_DIGS_C +#define BN_FAST_S_MP_SQR_C +#define BN_MP_2EXPT_C +#define BN_MP_ABS_C +#define BN_MP_ADD_C +#define BN_MP_ADD_D_C +#define BN_MP_ADDMOD_C +#define BN_MP_AND_C +#define BN_MP_CLAMP_C +#define BN_MP_CLEAR_C +#define BN_MP_CLEAR_MULTI_C +#define BN_MP_CMP_C +#define BN_MP_CMP_D_C +#define BN_MP_CMP_MAG_C +#define BN_MP_CNT_LSB_C +#define BN_MP_COPY_C +#define BN_MP_COUNT_BITS_C +#define BN_MP_DIV_C +#define BN_MP_DIV_2_C +#define BN_MP_DIV_2D_C +#define BN_MP_DIV_3_C +#define BN_MP_DIV_D_C +#define BN_MP_DR_IS_MODULUS_C +#define BN_MP_DR_REDUCE_C +#define BN_MP_DR_SETUP_C +#define BN_MP_EXCH_C +#define BN_MP_EXPT_D_C +#define BN_MP_EXPTMOD_C +#define BN_MP_EXPTMOD_FAST_C +#define BN_MP_EXTEUCLID_C +#define BN_MP_FREAD_C +#define BN_MP_FWRITE_C +#define BN_MP_GCD_C +#define BN_MP_GET_INT_C +#define BN_MP_GROW_C +#define BN_MP_INIT_C +#define BN_MP_INIT_COPY_C +#define BN_MP_INIT_MULTI_C +#define BN_MP_INIT_SET_C +#define BN_MP_INIT_SET_INT_C +#define BN_MP_INIT_SIZE_C +#define BN_MP_INVMOD_C +#define BN_MP_INVMOD_SLOW_C +#define BN_MP_IS_SQUARE_C +#define BN_MP_JACOBI_C +#define BN_MP_KARATSUBA_MUL_C +#define BN_MP_KARATSUBA_SQR_C +#define BN_MP_LCM_C +#define BN_MP_LSHD_C +#define BN_MP_MOD_C +#define BN_MP_MOD_2D_C +#define BN_MP_MOD_D_C +#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +#define BN_MP_MONTGOMERY_REDUCE_C +#define BN_MP_MONTGOMERY_SETUP_C +#define BN_MP_MUL_C +#define BN_MP_MUL_2_C +#define BN_MP_MUL_2D_C +#define BN_MP_MUL_D_C +#define BN_MP_MULMOD_C +#define BN_MP_N_ROOT_C +#define BN_MP_NEG_C +#define BN_MP_OR_C +#define BN_MP_PRIME_FERMAT_C +#define BN_MP_PRIME_IS_DIVISIBLE_C +#define BN_MP_PRIME_IS_PRIME_C +#define BN_MP_PRIME_MILLER_RABIN_C +#define BN_MP_PRIME_NEXT_PRIME_C +#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C +#define BN_MP_PRIME_RANDOM_EX_C +#define BN_MP_RADIX_SIZE_C +#define BN_MP_RADIX_SMAP_C +#define BN_MP_RAND_C +#define BN_MP_READ_RADIX_C +#define BN_MP_READ_SIGNED_BIN_C +#define BN_MP_READ_UNSIGNED_BIN_C +#define BN_MP_REDUCE_C +#define BN_MP_REDUCE_2K_C +#define BN_MP_REDUCE_2K_L_C +#define BN_MP_REDUCE_2K_SETUP_C +#define BN_MP_REDUCE_2K_SETUP_L_C +#define BN_MP_REDUCE_IS_2K_C +#define BN_MP_REDUCE_IS_2K_L_C +#define BN_MP_REDUCE_SETUP_C +#define BN_MP_RSHD_C +#define BN_MP_SET_C +#define BN_MP_SET_INT_C +#define BN_MP_SHRINK_C +#define BN_MP_SIGNED_BIN_SIZE_C +#define BN_MP_SQR_C +#define BN_MP_SQRMOD_C +#define BN_MP_SQRT_C +#define BN_MP_SUB_C +#define BN_MP_SUB_D_C +#define BN_MP_SUBMOD_C +#define BN_MP_TO_SIGNED_BIN_C +#define BN_MP_TO_SIGNED_BIN_N_C +#define BN_MP_TO_UNSIGNED_BIN_C +#define BN_MP_TO_UNSIGNED_BIN_N_C +#define BN_MP_TOOM_MUL_C +#define BN_MP_TOOM_SQR_C +#define BN_MP_TORADIX_C +#define BN_MP_TORADIX_N_C +#define BN_MP_UNSIGNED_BIN_SIZE_C +#define BN_MP_XOR_C +#define BN_MP_ZERO_C +#define BN_PRIME_TAB_C +#define BN_REVERSE_C +#define BN_S_MP_ADD_C +#define BN_S_MP_EXPTMOD_C +#define BN_S_MP_MUL_DIGS_C +#define BN_S_MP_MUL_HIGH_DIGS_C +#define BN_S_MP_SQR_C +#define BN_S_MP_SUB_C +#define BNCORE_C +#endif + +#if defined(BN_ERROR_C) + #define BN_MP_ERROR_TO_STRING_C +#endif + +#if defined(BN_FAST_MP_INVMOD_C) + #define BN_MP_ISEVEN_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_COPY_C + #define BN_MP_MOD_C + #define BN_MP_SET_C + #define BN_MP_DIV_2_C + #define BN_MP_ISODD_C + #define BN_MP_SUB_C + #define BN_MP_CMP_C + #define BN_MP_ISZERO_C + #define BN_MP_CMP_D_C + #define BN_MP_ADD_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C) + #define BN_MP_GROW_C + #define BN_MP_RSHD_C + #define BN_MP_CLAMP_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_FAST_S_MP_MUL_DIGS_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_SQR_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_2EXPT_C) + #define BN_MP_ZERO_C + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_ABS_C) + #define BN_MP_COPY_C +#endif + +#if defined(BN_MP_ADD_C) + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_ADD_D_C) + #define BN_MP_GROW_C + #define BN_MP_SUB_D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_ADDMOD_C) + #define BN_MP_INIT_C + #define BN_MP_ADD_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_AND_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CLAMP_C) +#endif + +#if defined(BN_MP_CLEAR_C) +#endif + +#if defined(BN_MP_CLEAR_MULTI_C) + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CMP_C) + #define BN_MP_CMP_MAG_C +#endif + +#if defined(BN_MP_CMP_D_C) +#endif + +#if defined(BN_MP_CMP_MAG_C) +#endif + +#if defined(BN_MP_CNT_LSB_C) + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_COPY_C) + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_COUNT_BITS_C) +#endif + +#if defined(BN_MP_DIV_C) + #define BN_MP_ISZERO_C + #define BN_MP_CMP_MAG_C + #define BN_MP_COPY_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_SET_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_ABS_C + #define BN_MP_MUL_2D_C + #define BN_MP_CMP_C + #define BN_MP_SUB_C + #define BN_MP_ADD_C + #define BN_MP_DIV_2D_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_INIT_C + #define BN_MP_INIT_COPY_C + #define BN_MP_LSHD_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_D_C + #define BN_MP_CLAMP_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_2_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_DIV_2D_C) + #define BN_MP_COPY_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_C + #define BN_MP_MOD_2D_C + #define BN_MP_CLEAR_C + #define BN_MP_RSHD_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_DIV_3_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_D_C) + #define BN_MP_ISZERO_C + #define BN_MP_COPY_C + #define BN_MP_DIV_2D_C + #define BN_MP_DIV_3_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DR_IS_MODULUS_C) +#endif + +#if defined(BN_MP_DR_REDUCE_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_DR_SETUP_C) +#endif + +#if defined(BN_MP_EXCH_C) +#endif + +#if defined(BN_MP_EXPT_D_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_SET_C + #define BN_MP_SQR_C + #define BN_MP_CLEAR_C + #define BN_MP_MUL_C +#endif + +#if defined(BN_MP_EXPTMOD_C) + #define BN_MP_INIT_C + #define BN_MP_INVMOD_C + #define BN_MP_CLEAR_C + #define BN_MP_ABS_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_REDUCE_IS_2K_L_C + #define BN_S_MP_EXPTMOD_C + #define BN_MP_DR_IS_MODULUS_C + #define BN_MP_REDUCE_IS_2K_C + #define BN_MP_ISODD_C + #define BN_MP_EXPTMOD_FAST_C +#endif + +#if defined(BN_MP_EXPTMOD_FAST_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C + #define BN_MP_MONTGOMERY_SETUP_C + #define BN_FAST_MP_MONTGOMERY_REDUCE_C + #define BN_MP_MONTGOMERY_REDUCE_C + #define BN_MP_DR_SETUP_C + #define BN_MP_DR_REDUCE_C + #define BN_MP_REDUCE_2K_SETUP_C + #define BN_MP_REDUCE_2K_C + #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C + #define BN_MP_MULMOD_C + #define BN_MP_SET_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_SQR_C + #define BN_MP_MUL_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_EXTEUCLID_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_SET_C + #define BN_MP_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_C + #define BN_MP_MUL_C + #define BN_MP_SUB_C + #define BN_MP_NEG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_FREAD_C) + #define BN_MP_ZERO_C + #define BN_MP_S_RMAP_C + #define BN_MP_MUL_D_C + #define BN_MP_ADD_D_C + #define BN_MP_CMP_D_C +#endif + +#if defined(BN_MP_FWRITE_C) + #define BN_MP_RADIX_SIZE_C + #define BN_MP_TORADIX_C +#endif + +#if defined(BN_MP_GCD_C) + #define BN_MP_ISZERO_C + #define BN_MP_ABS_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_S_MP_SUB_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_GET_INT_C) +#endif + +#if defined(BN_MP_GROW_C) +#endif + +#if defined(BN_MP_INIT_C) +#endif + +#if defined(BN_MP_INIT_COPY_C) + #define BN_MP_COPY_C +#endif + +#if defined(BN_MP_INIT_MULTI_C) + #define BN_MP_ERR_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_INIT_SET_C) + #define BN_MP_INIT_C + #define BN_MP_SET_C +#endif + +#if defined(BN_MP_INIT_SET_INT_C) + #define BN_MP_INIT_C + #define BN_MP_SET_INT_C +#endif + +#if defined(BN_MP_INIT_SIZE_C) + #define BN_MP_INIT_C +#endif + +#if defined(BN_MP_INVMOD_C) + #define BN_MP_ISZERO_C + #define BN_MP_ISODD_C + #define BN_FAST_MP_INVMOD_C + #define BN_MP_INVMOD_SLOW_C +#endif + +#if defined(BN_MP_INVMOD_SLOW_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_ISEVEN_C + #define BN_MP_SET_C + #define BN_MP_DIV_2_C + #define BN_MP_ISODD_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_CMP_C + #define BN_MP_CMP_D_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_IS_SQUARE_C) + #define BN_MP_MOD_D_C + #define BN_MP_INIT_SET_INT_C + #define BN_MP_MOD_C + #define BN_MP_GET_INT_C + #define BN_MP_SQRT_C + #define BN_MP_SQR_C + #define BN_MP_CMP_MAG_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_JACOBI_C) + #define BN_MP_CMP_D_C + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_MOD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KARATSUBA_MUL_C) + #define BN_MP_MUL_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_SUB_C + #define BN_MP_ADD_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KARATSUBA_SQR_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_SQR_C + #define BN_MP_SUB_C + #define BN_S_MP_ADD_C + #define BN_MP_LSHD_C + #define BN_MP_ADD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_LCM_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_GCD_C + #define BN_MP_CMP_MAG_C + #define BN_MP_DIV_C + #define BN_MP_MUL_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_LSHD_C) + #define BN_MP_GROW_C + #define BN_MP_RSHD_C +#endif + +#if defined(BN_MP_MOD_C) + #define BN_MP_INIT_C + #define BN_MP_DIV_C + #define BN_MP_CLEAR_C + #define BN_MP_ADD_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_MOD_2D_C) + #define BN_MP_ZERO_C + #define BN_MP_COPY_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MOD_D_C) + #define BN_MP_DIV_D_C +#endif + +#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_2EXPT_C + #define BN_MP_SET_C + #define BN_MP_MUL_2_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_REDUCE_C) + #define BN_FAST_MP_MONTGOMERY_REDUCE_C + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C + #define BN_MP_RSHD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_SETUP_C) +#endif + +#if defined(BN_MP_MUL_C) + #define BN_MP_TOOM_MUL_C + #define BN_MP_KARATSUBA_MUL_C + #define BN_FAST_S_MP_MUL_DIGS_C + #define BN_S_MP_MUL_C + #define BN_S_MP_MUL_DIGS_C +#endif + +#if defined(BN_MP_MUL_2_C) + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_MUL_2D_C) + #define BN_MP_COPY_C + #define BN_MP_GROW_C + #define BN_MP_LSHD_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MUL_D_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MULMOD_C) + #define BN_MP_INIT_C + #define BN_MP_MUL_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_N_ROOT_C) + #define BN_MP_INIT_C + #define BN_MP_SET_C + #define BN_MP_COPY_C + #define BN_MP_EXPT_D_C + #define BN_MP_MUL_C + #define BN_MP_SUB_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_C + #define BN_MP_CMP_C + #define BN_MP_SUB_D_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_NEG_C) + #define BN_MP_COPY_C + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_OR_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_FERMAT_C) + #define BN_MP_CMP_D_C + #define BN_MP_INIT_C + #define BN_MP_EXPTMOD_C + #define BN_MP_CMP_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_IS_DIVISIBLE_C) + #define BN_MP_MOD_D_C +#endif + +#if defined(BN_MP_PRIME_IS_PRIME_C) + #define BN_MP_CMP_D_C + #define BN_MP_PRIME_IS_DIVISIBLE_C + #define BN_MP_INIT_C + #define BN_MP_SET_C + #define BN_MP_PRIME_MILLER_RABIN_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_MILLER_RABIN_C) + #define BN_MP_CMP_D_C + #define BN_MP_INIT_COPY_C + #define BN_MP_SUB_D_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_EXPTMOD_C + #define BN_MP_CMP_C + #define BN_MP_SQRMOD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_NEXT_PRIME_C) + #define BN_MP_CMP_D_C + #define BN_MP_SET_C + #define BN_MP_SUB_D_C + #define BN_MP_ISEVEN_C + #define BN_MP_MOD_D_C + #define BN_MP_INIT_C + #define BN_MP_ADD_D_C + #define BN_MP_PRIME_MILLER_RABIN_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C) +#endif + +#if defined(BN_MP_PRIME_RANDOM_EX_C) + #define BN_MP_READ_UNSIGNED_BIN_C + #define BN_MP_PRIME_IS_PRIME_C + #define BN_MP_SUB_D_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_D_C +#endif + +#if defined(BN_MP_RADIX_SIZE_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_RADIX_SMAP_C) + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_RAND_C) + #define BN_MP_ZERO_C + #define BN_MP_ADD_D_C + #define BN_MP_LSHD_C +#endif + +#if defined(BN_MP_READ_RADIX_C) + #define BN_MP_ZERO_C + #define BN_MP_S_RMAP_C + #define BN_MP_RADIX_SMAP_C + #define BN_MP_MUL_D_C + #define BN_MP_ADD_D_C + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_READ_SIGNED_BIN_C) + #define BN_MP_READ_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_READ_UNSIGNED_BIN_C) + #define BN_MP_GROW_C + #define BN_MP_ZERO_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_REDUCE_C) + #define BN_MP_REDUCE_SETUP_C + #define BN_MP_INIT_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_C + #define BN_S_MP_MUL_HIGH_DIGS_C + #define BN_FAST_S_MP_MUL_HIGH_DIGS_C + #define BN_MP_MOD_2D_C + #define BN_S_MP_MUL_DIGS_C + #define BN_MP_SUB_C + #define BN_MP_CMP_D_C + #define BN_MP_SET_C + #define BN_MP_LSHD_C + #define BN_MP_ADD_C + #define BN_MP_CMP_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_DIV_2D_C + #define BN_MP_MUL_D_C + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_L_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_DIV_2D_C + #define BN_MP_MUL_C + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_2EXPT_C + #define BN_MP_CLEAR_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_L_C) + #define BN_MP_INIT_C + #define BN_MP_2EXPT_C + #define BN_MP_COUNT_BITS_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_C) + #define BN_MP_REDUCE_2K_C + #define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_L_C) +#endif + +#if defined(BN_MP_REDUCE_SETUP_C) + #define BN_MP_2EXPT_C + #define BN_MP_DIV_C +#endif + +#if defined(BN_MP_RSHD_C) + #define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_C) + #define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_INT_C) + #define BN_MP_ZERO_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SHRINK_C) +#endif + +#if defined(BN_MP_SIGNED_BIN_SIZE_C) + #define BN_MP_UNSIGNED_BIN_SIZE_C +#endif + +#if defined(BN_MP_SQR_C) + #define BN_MP_TOOM_SQR_C + #define BN_MP_KARATSUBA_SQR_C + #define BN_FAST_S_MP_SQR_C + #define BN_S_MP_SQR_C +#endif + +#if defined(BN_MP_SQRMOD_C) + #define BN_MP_INIT_C + #define BN_MP_SQR_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_SQRT_C) + #define BN_MP_N_ROOT_C + #define BN_MP_ISZERO_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_DIV_C + #define BN_MP_ADD_C + #define BN_MP_DIV_2_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_SUB_C) + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_SUB_D_C) + #define BN_MP_GROW_C + #define BN_MP_ADD_D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SUBMOD_C) + #define BN_MP_INIT_C + #define BN_MP_SUB_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_C) + #define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_N_C) + #define BN_MP_SIGNED_BIN_SIZE_C + #define BN_MP_TO_SIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_2D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_N_C) + #define BN_MP_UNSIGNED_BIN_SIZE_C + #define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TOOM_MUL_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_2D_C + #define BN_MP_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2D_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_3_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TOOM_SQR_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_2D_C + #define BN_MP_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_SQR_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2D_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_3_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TORADIX_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_TORADIX_N_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_UNSIGNED_BIN_SIZE_C) + #define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_XOR_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_ZERO_C) +#endif + +#if defined(BN_PRIME_TAB_C) +#endif + +#if defined(BN_REVERSE_C) +#endif + +#if defined(BN_S_MP_ADD_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_S_MP_EXPTMOD_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C + #define BN_MP_REDUCE_SETUP_C + #define BN_MP_REDUCE_C + #define BN_MP_REDUCE_2K_SETUP_L_C + #define BN_MP_REDUCE_2K_L_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_SQR_C + #define BN_MP_MUL_C + #define BN_MP_SET_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_S_MP_MUL_DIGS_C) + #define BN_FAST_S_MP_MUL_DIGS_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_MUL_HIGH_DIGS_C) + #define BN_FAST_S_MP_MUL_HIGH_DIGS_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SQR_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SUB_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BNCORE_C) +#endif + +#ifdef LTM3 +#define LTM_LAST +#endif +#include "mpi_superclass.h" +#include "mpi_class.h" +#else +#define LTM_LAST +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpi_superclass.h Sat Feb 05 01:09:17 2011 +0000 @@ -0,0 +1,73 @@ +/* super class file for PK algos */ + +/* default ... include all MPI */ +#define LTM_ALL + +/* RSA only (does not support DH/DSA/ECC) */ +/* #define SC_RSA_1 */ + +/* For reference.... On an Athlon64 optimizing for speed... + + LTM's mpi.o with all functions [striped] is 142KiB in size. + +*/ + +/* Works for RSA only, mpi.o is 68KiB */ +#ifdef SC_RSA_1 + #define BN_MP_SHRINK_C + #define BN_MP_LCM_C + #define BN_MP_PRIME_RANDOM_EX_C + #define BN_MP_INVMOD_C + #define BN_MP_GCD_C + #define BN_MP_MOD_C + #define BN_MP_MULMOD_C + #define BN_MP_ADDMOD_C + #define BN_MP_EXPTMOD_C + #define BN_MP_SET_INT_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_UNSIGNED_BIN_SIZE_C + #define BN_MP_TO_UNSIGNED_BIN_C + #define BN_MP_MOD_D_C + #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C + #define BN_REVERSE_C + #define BN_PRIME_TAB_C + + /* other modifiers */ + #define BN_MP_DIV_SMALL /* Slower division, not critical */ + + /* here we are on the last pass so we turn things off. The functions classes are still there + * but we remove them specifically from the build. This also invokes tweaks in functions + * like removing support for even moduli, etc... + */ +#ifdef LTM_LAST + #undef BN_MP_TOOM_MUL_C + #undef BN_MP_TOOM_SQR_C + #undef BN_MP_KARATSUBA_MUL_C + #undef BN_MP_KARATSUBA_SQR_C + #undef BN_MP_REDUCE_C + #undef BN_MP_REDUCE_SETUP_C + #undef BN_MP_DR_IS_MODULUS_C + #undef BN_MP_DR_SETUP_C + #undef BN_MP_DR_REDUCE_C + #undef BN_MP_REDUCE_IS_2K_C + #undef BN_MP_REDUCE_2K_SETUP_C + #undef BN_MP_REDUCE_2K_C + #undef BN_S_MP_EXPTMOD_C + #undef BN_MP_DIV_3_C + #undef BN_S_MP_MUL_HIGH_DIGS_C + #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C + #undef BN_FAST_MP_INVMOD_C + + /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold + * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] + * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without + * trouble. + */ + #undef BN_S_MP_MUL_DIGS_C + #undef BN_S_MP_SQR_C + #undef BN_MP_MONTGOMERY_REDUCE_C +#endif + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/os_settings.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,216 @@
+/* os_settings.h
+ *
+ * Copyright (C) 2006-2010 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Place OS specific preprocessor flags, defines, includes here, will be
+ included into every file because types.h includes it */
+
+#ifndef CTAO_CRYPT_OS_SETTINGS_H
+#define CTAO_CRYPT_OS_SETTINGS_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Uncomment next line if using IPHONE */
+/* #define IPHONE */
+
+/* Uncomment next line if using ThreadX */
+/* #define THREADX */
+
+/* Uncomment next line if using Micrium ucOS */
+/* #define MICRIUM */
+
+
+#ifdef IPHONE
+ #define SIZEOF_LONG_LONG 8
+#endif
+
+#ifdef THREADX
+ #define SIZEOF_LONG_LONG 8
+#endif
+
+#define MBED
+
+#ifdef MBED
+
+ #define SINGLE_THREADED
+ #define CYASSL_USER_IO
+ #define NO_WRITEV
+ #define NO_DEV_RANDOM
+ #define NO_SHA512
+ #define NO_DH
+ #define NO_DSA
+ #define NO_HC128
+
+#endif /* MBED */
+
+
+#ifdef MICRIUM
+
+ #include "net_cfg.h"
+ #include "cyassl_cfg.h"
+ #include "net_secure_os.h"
+
+ #define CYASSL_TYPES
+
+ typedef CPU_INT08U byte;
+ typedef CPU_INT16U word16;
+ typedef CPU_INT32U word32;
+
+ #if (NET_SECURE_MGR_CFG_WORD_SIZE == CPU_WORD_SIZE_32)
+ #define SIZEOF_LONG 8
+ #undef SIZEOF_LONG_LONG
+ #else
+ #undef SIZEOF_LONG
+ #define SIZEOF_LONG_LONG 8
+ #endif
+
+ #define STRING_USER
+
+ #define XSTRLEN(pstr) ((CPU_SIZE_T)Str_Len((CPU_CHAR *)(pstr)))
+ #define XSTRNCPY(pstr_dest, pstr_src, len_max) \
+ ((CPU_CHAR *)Str_Copy_N((CPU_CHAR *)(pstr_dest), \
+ (CPU_CHAR *)(pstr_src), (CPU_SIZE_T)(len_max)))
+ #define XSTRNCMP(pstr_1, pstr_2, len_max) \
+ ((CPU_INT16S)Str_Cmp_N((CPU_CHAR *)(pstr_1), \
+ (CPU_CHAR *)(pstr_2), (CPU_SIZE_T)(len_max)))
+ #define XSTRSTR(pstr, pstr_srch) \
+ ((CPU_CHAR *)Str_Str((CPU_CHAR *)(pstr), \
+ (CPU_CHAR *)(pstr_srch)))
+ #define XMEMSET(pmem, data_val, size) \
+ ((void)Mem_Set((void *)(pmem), (CPU_INT08U) (data_val), \
+ (CPU_SIZE_T)(size)))
+ #define XMEMCPY(pdest, psrc, size) ((void)Mem_Copy((void *)(pdest), \
+ (void *)(psrc), (CPU_SIZE_T)(size)))
+ #define XMEMCMP(pmem_1, pmem_2, size) \
+ (((CPU_BOOLEAN)Mem_Cmp((void *)(pmem_1), (void *)(pmem_2), \
+ (CPU_SIZE_T)(size))) ? DEF_NO : DEF_YES)
+
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ #define MICRIUM_MALLOC
+ #define XMALLOC(s, h, type) (((type) <= DYNAMIC_TYPE_SIGNER) ? \
+ ((void *)NetSecure_Malloc((CPU_INT08U)(type), \
+ (CPU_SIZE_T)(s))) : malloc(s))
+ #define XFREE(p, h, type) (((type) <= DYNAMIC_TYPE_SIGNER) ? \
+ (NetSecure_Free((CPU_INT08U)(type), (p))) : free((p)))
+ #define XREALLOC(p, n, h, t) realloc((p), (n))
+ #endif
+
+ #if (NET_SECURE_MGR_CFG_FS_EN == DEF_ENABLED)
+ #undef NO_FILESYSTEM
+ #else
+ #define NO_FILESYSTEM
+ #endif
+
+ #if (CYASSL_CFG_TRACE_LEVEL == CYASSL_TRACE_LEVEL_DBG)
+ #define DEBUG_CYASSL
+ #else
+ #undef DEBUG_CYASSL
+ #endif
+
+ #if (CYASSL_CFG_OPENSSL_EN == DEF_ENABLED)
+ #define OPENSSL_EXTRA
+ #else
+ #undef OPENSSL_EXTRA
+ #endif
+
+ #if (CYASSL_CFG_MULTI_THREAD_EN == DEF_ENABLED)
+ #undef SINGLE_THREADED
+ #else
+ #define SINGLE_THREADED
+ #endif
+
+ #if (CYASSL_CFG_DH_EN == DEF_ENABLED)
+ #undef NO_DH
+ #else
+ #define NO_DH
+ #endif
+
+ #if (CYASSL_CFG_DSA_EN == DEF_ENABLED)
+ #undef NO_DSA
+ #else
+ #define NO_DSA
+ #endif
+
+ #if (CYASSL_CFG_PSK_EN == DEF_ENABLED)
+ #undef NO_PSK
+ #else
+ #define NO_PSK
+ #endif
+
+ #if (CYASSL_CFG_3DES_EN == DEF_ENABLED)
+ #undef NO_DES
+ #else
+ #define NO_DES
+ #endif
+
+ #if (CYASSL_CFG_AES_EN == DEF_ENABLED)
+ #undef NO_AES
+ #else
+ #define NO_AES
+ #endif
+
+ #if (CYASSL_CFG_RC4_EN == DEF_ENABLED)
+ #undef NO_RC4
+ #else
+ #define NO_RC4
+ #endif
+
+ #if (CYASSL_CFG_RABBIT_EN == DEF_ENABLED)
+ #undef NO_RABBIT
+ #else
+ #define NO_RABBIT
+ #endif
+
+ #if (CYASSL_CFG_HC128_EN == DEF_ENABLED)
+ #undef NO_HC128
+ #else
+ #define NO_HC128
+ #endif
+
+ #if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
+ #define BIG_ENDIAN_ORDER
+ #else
+ #undef BIG_ENDIAN_ORDER
+ #define LITTLE_ENDIAN_ORDER
+ #endif
+
+
+ #define NO_MD4
+ #define NO_WRITEV
+ #define NO_DEV_RANDOM
+ #define CYASSL_USER_IO
+ #define LARGE_STATIC_BUFFERS
+ #define CYASSL_DER_LOAD
+ #undef CYASSL_DTLS
+
+#endif /* MICRIUM */
+
+/* Place any other flags or defines here */
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* CTAO_CRYPT_OS_SETTINGS_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pwdbased.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,76 @@
+/* pwdbased.c
+ *
+ * Copyright (C) 2006-2010 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_PWDBASED
+
+#include "pwdbased.h"
+
+
+int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
+ int sLen, int iterations, int kLen, int hashType)
+{
+ Md5 md5;
+ Sha sha;
+ int hLen = (hashType == MD5) ? MD5_DIGEST_SIZE : SHA_DIGEST_SIZE;
+ int i;
+ byte buffer[SHA_DIGEST_SIZE]; /* max size */
+
+ if (hashType != MD5 && hashType != SHA)
+ return -1;
+
+ if (kLen > hLen)
+ return -1;
+
+ if (iterations < 1)
+ return -1;
+
+ if (hashType == MD5) {
+ InitMd5(&md5);
+ Md5Update(&md5, passwd, pLen);
+ Md5Update(&md5, salt, sLen);
+ Md5Final(&md5, buffer);
+ }
+ else {
+ InitSha(&sha);
+ ShaUpdate(&sha, passwd, pLen);
+ ShaUpdate(&sha, salt, sLen);
+ ShaFinal(&sha, buffer);
+ }
+
+ for (i = 1; i < iterations; i++) {
+ if (hashType == MD5) {
+ Md5Update(&md5, buffer, hLen);
+ Md5Final(&md5, buffer);
+ }
+ else {
+ ShaUpdate(&sha, buffer, hLen);
+ ShaFinal(&sha, buffer);
+ }
+ }
+ XMEMCPY(output, buffer, kLen);
+
+ return 0;
+}
+
+
+#endif /* NO_PWDBASED */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pwdbased.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,47 @@
+/* pwdbased.h
+ *
+ * Copyright (C) 2006-2010 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_PWDBASED
+
+#ifndef CTAO_CRYPT_PWDBASED_H
+#define CTAO_CRYPT_PWDBASED_H
+
+#include "types.h"
+#include "ctc_md5.h" /* for hash type */
+#include "ctc_sha.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+int PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
+ int sLen, int iterations, int kLen, int hashType);
+
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_PWDBASED_H */
+#endif /* NO_PWDBASED */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rabbit.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,239 @@
+/* rabbit.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_RABBIT
+
+#include "rabbit.h"
+#include "misc.c"
+
+
+#ifdef BIG_ENDIAN_ORDER
+ #define LITTLE32(x) ByteReverseWord32(x)
+#else
+ #define LITTLE32(x) (x)
+#endif
+
+#define U32V(x) (word32)(x)
+
+
+/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */
+/* the upper 32 bits XOR the lower 32 bits */
+static word32 RABBIT_g_func(word32 x)
+{
+ /* Temporary variables */
+ word32 a, b, h, l;
+
+ /* Construct high and low argument for squaring */
+ a = x&0xFFFF;
+ b = x>>16;
+
+ /* Calculate high and low result of squaring */
+ h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b;
+ l = x*x;
+
+ /* Return high XOR low */
+ return U32V(h^l);
+}
+
+
+/* Calculate the next internal state */
+static void RABBIT_next_state(RabbitCtx* ctx)
+{
+ /* Temporary variables */
+ word32 g[8], c_old[8], i;
+
+ /* Save old counter values */
+ for (i=0; i<8; i++)
+ c_old[i] = ctx->c[i];
+
+ /* Calculate new counter values */
+ ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry);
+ ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0]));
+ ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1]));
+ ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2]));
+ ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3]));
+ ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4]));
+ ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5]));
+ ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6]));
+ ctx->carry = (ctx->c[7] < c_old[7]);
+
+ /* Calculate the g-values */
+ for (i=0;i<8;i++)
+ g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i]));
+
+ /* Calculate new state values */
+ ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16));
+ ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]);
+ ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16));
+ ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]);
+ ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16));
+ ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]);
+ ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16));
+ ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]);
+}
+
+
+/* IV setup */
+static void RabbitSetIV(Rabbit* ctx, const byte* iv)
+{
+ /* Temporary variables */
+ word32 i0, i1, i2, i3, i;
+
+ /* Generate four subvectors */
+ i0 = LITTLE32(*(word32*)(iv+0));
+ i2 = LITTLE32(*(word32*)(iv+4));
+ i1 = (i0>>16) | (i2&0xFFFF0000);
+ i3 = (i2<<16) | (i0&0x0000FFFF);
+
+ /* Modify counter values */
+ ctx->workCtx.c[0] = ctx->masterCtx.c[0] ^ i0;
+ ctx->workCtx.c[1] = ctx->masterCtx.c[1] ^ i1;
+ ctx->workCtx.c[2] = ctx->masterCtx.c[2] ^ i2;
+ ctx->workCtx.c[3] = ctx->masterCtx.c[3] ^ i3;
+ ctx->workCtx.c[4] = ctx->masterCtx.c[4] ^ i0;
+ ctx->workCtx.c[5] = ctx->masterCtx.c[5] ^ i1;
+ ctx->workCtx.c[6] = ctx->masterCtx.c[6] ^ i2;
+ ctx->workCtx.c[7] = ctx->masterCtx.c[7] ^ i3;
+
+ /* Copy state variables */
+ for (i=0; i<8; i++)
+ ctx->workCtx.x[i] = ctx->masterCtx.x[i];
+ ctx->workCtx.carry = ctx->masterCtx.carry;
+
+ /* Iterate the system four times */
+ for (i=0; i<4; i++)
+ RABBIT_next_state(&(ctx->workCtx));
+}
+
+
+/* Key setup */
+void RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv)
+{
+ /* Temporary variables */
+ word32 k0, k1, k2, k3, i;
+
+ /* Generate four subkeys */
+ k0 = LITTLE32(*(word32*)(key+ 0));
+ k1 = LITTLE32(*(word32*)(key+ 4));
+ k2 = LITTLE32(*(word32*)(key+ 8));
+ k3 = LITTLE32(*(word32*)(key+12));
+
+ /* Generate initial state variables */
+ ctx->masterCtx.x[0] = k0;
+ ctx->masterCtx.x[2] = k1;
+ ctx->masterCtx.x[4] = k2;
+ ctx->masterCtx.x[6] = k3;
+ ctx->masterCtx.x[1] = U32V(k3<<16) | (k2>>16);
+ ctx->masterCtx.x[3] = U32V(k0<<16) | (k3>>16);
+ ctx->masterCtx.x[5] = U32V(k1<<16) | (k0>>16);
+ ctx->masterCtx.x[7] = U32V(k2<<16) | (k1>>16);
+
+ /* Generate initial counter values */
+ ctx->masterCtx.c[0] = rotlFixed(k2, 16);
+ ctx->masterCtx.c[2] = rotlFixed(k3, 16);
+ ctx->masterCtx.c[4] = rotlFixed(k0, 16);
+ ctx->masterCtx.c[6] = rotlFixed(k1, 16);
+ ctx->masterCtx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF);
+ ctx->masterCtx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF);
+ ctx->masterCtx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF);
+ ctx->masterCtx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF);
+
+ /* Clear carry bit */
+ ctx->masterCtx.carry = 0;
+
+ /* Iterate the system four times */
+ for (i=0; i<4; i++)
+ RABBIT_next_state(&(ctx->masterCtx));
+
+ /* Modify the counters */
+ for (i=0; i<8; i++)
+ ctx->masterCtx.c[i] ^= ctx->masterCtx.x[(i+4)&0x7];
+
+ /* Copy master instance to work instance */
+ for (i=0; i<8; i++) {
+ ctx->workCtx.x[i] = ctx->masterCtx.x[i];
+ ctx->workCtx.c[i] = ctx->masterCtx.c[i];
+ }
+ ctx->workCtx.carry = ctx->masterCtx.carry;
+
+ if (iv) RabbitSetIV(ctx, iv);
+}
+
+
+/* Encrypt/decrypt a message of any size */
+void RabbitProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen)
+{
+
+ /* Encrypt/decrypt all full blocks */
+ while (msglen >= 16) {
+ /* Iterate the system */
+ RABBIT_next_state(&(ctx->workCtx));
+
+ /* Encrypt/decrypt 16 bytes of data */
+ *(word32*)(output+ 0) = *(word32*)(input+ 0) ^
+ LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^
+ U32V(ctx->workCtx.x[3]<<16));
+ *(word32*)(output+ 4) = *(word32*)(input+ 4) ^
+ LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^
+ U32V(ctx->workCtx.x[5]<<16));
+ *(word32*)(output+ 8) = *(word32*)(input+ 8) ^
+ LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^
+ U32V(ctx->workCtx.x[7]<<16));
+ *(word32*)(output+12) = *(word32*)(input+12) ^
+ LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^
+ U32V(ctx->workCtx.x[1]<<16));
+
+ /* Increment pointers and decrement length */
+ input += 16;
+ output += 16;
+ msglen -= 16;
+ }
+
+ /* Encrypt/decrypt remaining data */
+ if (msglen) {
+
+ word32 i;
+ word32 tmp[4];
+ byte* buffer = (byte*)tmp;
+
+ /* Iterate the system */
+ RABBIT_next_state(&(ctx->workCtx));
+
+ /* Generate 16 bytes of pseudo-random data */
+ tmp[0] = LITTLE32(ctx->workCtx.x[0] ^
+ (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16));
+ tmp[1] = LITTLE32(ctx->workCtx.x[2] ^
+ (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16));
+ tmp[2] = LITTLE32(ctx->workCtx.x[4] ^
+ (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16));
+ tmp[3] = LITTLE32(ctx->workCtx.x[6] ^
+ (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16));
+
+ /* Encrypt/decrypt the data */
+ for (i=0; i<msglen; i++)
+ output[i] = input[i] ^ buffer[i];
+ }
+}
+
+
+
+#endif /* NO_RABBIT */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rabbit.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,60 @@
+/* rabbit.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef NO_RABBIT
+
+#ifndef CTAO_CRYPT_RABBIT_H
+#define CTAO_CRYPT_RABBIT_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/* Rabbit Context */
+typedef struct RabbitCtx {
+ word32 x[8];
+ word32 c[8];
+ word32 carry;
+} RabbitCtx;
+
+
+/* Rabbit stream cipher */
+typedef struct Rabbit {
+ RabbitCtx masterCtx;
+ RabbitCtx workCtx;
+} Rabbit;
+
+
+void RabbitProcess(Rabbit*, byte*, const byte*, word32);
+void RabbitSetKey(Rabbit*, const byte* key, const byte* iv);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_RABBIT_H */
+
+#endif /* NO_RABBIT */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/random.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,184 @@
+/* random.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* on HPUX 11 you may need to install /dev/random see
+ http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
+
+*/
+
+#include "random.h"
+#include "error.h"
+
+
+#if defined(USE_WINDOWS_API)
+ #define _WIN32_WINNT 0x0400
+ #include <windows.h>
+ #include <wincrypt.h>
+#else
+ #ifndef NO_DEV_RANDOM
+ #include <fcntl.h>
+ #include <unistd.h>
+ #else
+ /* include headers that may be needed to get good seed */
+ #endif
+#endif /* USE_WINDOWS_API */
+
+
+
+/* Get seed and key cipher */
+int InitRng(RNG* rng)
+{
+ byte key[32];
+ byte junk[256];
+
+ int ret = GenerateSeed(&rng->seed, key, sizeof(key));
+
+ if (ret == 0) {
+ Arc4SetKey(&rng->cipher, key, sizeof(key));
+ RNG_GenerateBlock(rng, junk, sizeof(junk)); /* rid initial state */
+ }
+
+ return ret;
+}
+
+
+/* place a generated block in output */
+void RNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
+{
+ XMEMSET(output, 0, sz);
+ Arc4Process(&rng->cipher, output, output, sz);
+}
+
+
+byte RNG_GenerateByte(RNG* rng)
+{
+ byte b;
+ RNG_GenerateBlock(rng, &b, 1);
+
+ return b;
+}
+
+
+#if defined(USE_WINDOWS_API)
+
+
+int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+ if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return WINCRYPT_E;
+
+ if (!CryptGenRandom(os->handle, sz, output))
+ return CRYPTGEN_E;
+
+ CryptReleaseContext(os->handle, 0);
+
+ return 0;
+}
+
+
+#elif defined(THREADX)
+
+#include "rtprand.h" /* rtp_rand () */
+#include "rtptime.h" /* rtp_get_system_msec() */
+
+
+int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+ int i;
+ rtp_srand(rtp_get_system_msec());
+
+ for (i = 0; i < sz; i++ ) {
+ output[i] = rtp_rand() % 256;
+ if ( (i % 8) == 7)
+ rtp_srand(rtp_get_system_msec());
+ }
+
+ return 0;
+}
+
+
+#elif defined(MICRIUM)
+
+int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+ #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
+ NetSecure_InitSeed(output, sz);
+ #endif
+ return 0;
+}
+
+
+#elif defined(MBED)
+
+int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+ int i;
+
+ for (i = 0; i < sz; i++)
+ output[i] = i;
+
+ return 0;
+}
+
+
+#elif defined(NO_DEV_RANDOM)
+
+#error "you need to write an os specific GenerateSeed() here"
+
+
+#else /* !USE_WINDOWS_API && !THREADX && !MICRIUM && !NO_DEV_RANDOM */
+
+
+/* may block */
+int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
+{
+ os->fd = open("/dev/urandom",O_RDONLY);
+ if (os->fd == -1) {
+ /* may still have /dev/random */
+ os->fd = open("/dev/random",O_RDONLY);
+ if (os->fd == -1)
+ return OPEN_RAN_E;
+ }
+
+ while (sz) {
+ int len = read(os->fd, output, sz);
+ if (len == -1)
+ return READ_RAN_E;
+
+ sz -= len;
+ output += len;
+
+ if (sz)
+#ifdef BLOCKING
+ sleep(0); /* context switch */
+#else
+ return RAN_BLOCK_E;
+#endif
+ }
+ close(os->fd);
+
+ return 0;
+}
+
+#endif /* USE_WINDOWS_API */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/random.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,72 @@
+/* random.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_RANDOM_H
+#define CTAO_CRYPT_RANDOM_H
+
+#include "arc4.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#if defined(USE_WINDOWS_API)
+ #if defined(_WIN64)
+ typedef unsigned __int64 ProviderHandle;
+ /* type HCRYPTPROV, avoid #include <windows.h> */
+ #else
+ typedef unsigned long ProviderHandle;
+ #endif
+#endif
+
+
+/* OS specific seeder */
+typedef struct OS_Seed {
+ #if defined(USE_WINDOWS_API)
+ ProviderHandle handle;
+ #else
+ int fd;
+ #endif
+} OS_Seed;
+
+int GenerateSeed(OS_Seed* os, byte* seed, word32 sz);
+
+
+/* secure Random Nnumber Generator */
+typedef struct RNG {
+ OS_Seed seed;
+ Arc4 cipher;
+} RNG;
+
+
+int InitRng(RNG*);
+void RNG_GenerateBlock(RNG*, byte*, word32 sz);
+byte RNG_GenerateByte(RNG*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_RANDOM_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,535 @@
+/* rsa.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+#include "ctc_rsa.h"
+#include "random.h"
+#include "error.h"
+
+#ifdef SHOW_GEN
+ #include <stdio.h>
+#endif
+
+
+enum {
+ RSA_PUBLIC_ENCRYPT = 0,
+ RSA_PUBLIC_DECRYPT = 1,
+ RSA_PRIVATE_ENCRYPT = 2,
+ RSA_PRIVATE_DECRYPT = 3,
+
+ RSA_BLOCK_TYPE_1 = 1,
+ RSA_BLOCK_TYPE_2 = 2,
+
+ RSA_MIN_SIZE = 512,
+ RSA_MAX_SIZE = 4096,
+
+ RSA_MIN_PAD_SZ = 11 /* seperator + 0 + pad value + 8 pads */
+};
+
+
+void InitRsaKey(RsaKey* key, void* heap)
+{
+ key->type = -1; /* haven't decdied yet */
+ key->heap = heap;
+
+/* TomsFastMath doesn't use memory allocation */
+#ifndef USE_FAST_MATH
+ key->n.dp = key->e.dp = 0; /* public alloc parts */
+
+ key->d.dp = key->p.dp = 0; /* private alloc parts */
+ key->q.dp = key->dP.dp = 0;
+ key->u.dp = key->dQ.dp = 0;
+#endif
+}
+
+
+void FreeRsaKey(RsaKey* key)
+{
+/* TomsFastMath doesn't use memory allocation */
+#ifndef USE_FAST_MATH
+ if (key->type == RSA_PRIVATE) {
+ mp_clear(&key->u);
+ mp_clear(&key->dQ);
+ mp_clear(&key->dP);
+ mp_clear(&key->q);
+ mp_clear(&key->p);
+ mp_clear(&key->d);
+ }
+ mp_clear(&key->e);
+ mp_clear(&key->n);
+#endif
+}
+
+static void RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
+ word32 pkcsBlockLen, byte padValue, RNG* rng)
+{
+ if (inputLen == 0) return;
+
+ pkcsBlock[0] = 0x0; /* set first byte to zero and advance */
+ pkcsBlock++; pkcsBlockLen--;
+ pkcsBlock[0] = padValue; /* insert padValue */
+
+ if (padValue == RSA_BLOCK_TYPE_1)
+ /* pad with 0xff bytes */
+ XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
+ else {
+ /* pad with non-zero random bytes */
+ word32 padLen = pkcsBlockLen - inputLen - 1, i;
+ RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
+
+ /* remove zeros */
+ for (i = 1; i < padLen; i++)
+ if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
+ }
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */
+ XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+
+static word32 RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
+ byte **output, byte padValue)
+{
+ word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
+ invalid = 0,
+ i = 1,
+ outputLen;
+
+ if (pkcsBlock[0] != 0x0) /* skip past zero */
+ invalid = 1;
+ pkcsBlock++; pkcsBlockLen--;
+
+ /* Require block type padValue */
+ invalid = (pkcsBlock[0] != padValue) || invalid;
+
+ /* skip past the padding until we find the separator */
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { /* null body */
+ }
+ if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0))
+ return 0;
+
+ outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return 0;
+
+ *output = (byte *)(pkcsBlock + i);
+ return outputLen;
+}
+
+
+static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
+ int type, RsaKey* key)
+{
+ #define ERROR_OUT(x) { ret = x; goto done;}
+
+ mp_int tmp;
+ int ret = 0;
+ word32 keyLen, len;
+
+ if (mp_init(&tmp) != MP_OKAY)
+ return MP_INIT_E;
+
+ if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
+ ERROR_OUT(MP_READ_E);
+
+ if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
+ #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */
+ if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
+ ERROR_OUT(MP_EXPTMOD_E);
+ #else
+ #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }
+
+ mp_int tmpa, tmpb;
+
+ if (mp_init(&tmpa) != MP_OKAY)
+ ERROR_OUT(MP_INIT_E);
+
+ if (mp_init(&tmpb) != MP_OKAY) {
+ mp_clear(&tmpa);
+ ERROR_OUT(MP_INIT_E);
+ }
+
+ /* tmpa = tmp^dP mod p */
+ if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
+ INNER_ERROR_OUT(MP_EXPTMOD_E);
+
+ /* tmpb = tmp^dQ mod q */
+ if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
+ INNER_ERROR_OUT(MP_EXPTMOD_E);
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
+ INNER_ERROR_OUT(MP_SUB_E);
+
+ if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
+ INNER_ERROR_OUT(MP_MULMOD_E);
+
+ /* tmp = tmpb + q * tmp */
+ if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
+ INNER_ERROR_OUT(MP_MUL_E);
+
+ if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
+ INNER_ERROR_OUT(MP_ADD_E);
+
+ inner_done:
+ mp_clear(&tmpa);
+ mp_clear(&tmpb);
+
+ if (ret != 0) return ret;
+
+ #endif /* RSA_LOW_MEM */
+ }
+ else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
+ if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
+ ERROR_OUT(MP_EXPTMOD_E);
+ }
+ else
+ ERROR_OUT(RSA_WRONG_TYPE_E);
+
+ keyLen = mp_unsigned_bin_size(&key->n);
+ if (keyLen > *outLen)
+ ERROR_OUT(RSA_BUFFER_E);
+
+ len = mp_unsigned_bin_size(&tmp);
+
+ /* pad front w/ zeros to match key length */
+ while (len < keyLen) {
+ *out++ = 0x00;
+ len++;
+ }
+
+ *outLen = keyLen;
+
+ /* convert */
+ if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
+ ERROR_OUT(MP_TO_E);
+
+done:
+ mp_clear(&tmp);
+ return ret;
+}
+
+
+
+int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key, RNG* rng)
+{
+ int sz = mp_unsigned_bin_size(&key->n), ret;
+
+ if (sz > (int)outLen)
+ return RSA_BUFFER_E;
+
+ if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
+ return RSA_BUFFER_E;
+
+ RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng);
+
+ if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PUBLIC_ENCRYPT, key)) < 0)
+ sz = ret;
+
+ return sz;
+}
+
+
+int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
+{
+ int plainLen, ret;
+
+ if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
+ < 0) {
+ return ret;
+ }
+
+ plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
+
+ return plainLen;
+}
+
+int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key)
+{
+ int plainLen, ret;
+ byte* tmp;
+ byte* pad = 0;
+
+ if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
+ return MEMORY_E;
+
+ XMEMCPY(tmp, in, inLen);
+
+ if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key))
+ < 0) {
+ XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
+ return ret;
+ }
+ XMEMCPY(out, pad, plainLen);
+ XMEMSET(tmp, 0x00, inLen);
+
+ XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
+ return plainLen;
+}
+
+
+/* for Rsa Verify */
+int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
+{
+ int plainLen, ret;
+
+ if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key))
+ < 0) {
+ return ret;
+ }
+
+ plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
+
+ return plainLen;
+}
+
+int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key)
+{
+ int plainLen, ret;
+ byte* tmp;
+ byte* pad = 0;
+
+ if ( !(tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA)) )
+ return MEMORY_E;
+
+ XMEMCPY(tmp, in, inLen);
+
+ if ((ret = plainLen = RsaSSL_VerifyInline(tmp, inLen, &pad, key))
+ < 0) {
+ XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
+ return ret;
+ }
+
+ XMEMCPY(out, pad, plainLen);
+ XMEMSET(tmp, 0x00, inLen);
+
+ XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
+ return plainLen;
+}
+
+
+/* for Rsa Sign */
+int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
+ RsaKey* key, RNG* rng)
+{
+ int sz = mp_unsigned_bin_size(&key->n), ret;
+
+ if (sz > (int)outLen)
+ return RSA_BUFFER_E;
+
+ if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
+ return RSA_BUFFER_E;
+
+ RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng);
+
+ if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PRIVATE_ENCRYPT,key)) < 0)
+ sz = ret;
+
+ return sz;
+}
+
+
+int RsaEncryptSize(RsaKey* key)
+{
+ return mp_unsigned_bin_size(&key->n);
+}
+
+
+#ifdef CYASSL_KEY_GEN
+
+static const int USE_BBS = 1;
+
+static int rand_prime(mp_int* N, int len, RNG* rng, void* heap)
+{
+ int err, res, type;
+ byte* buf;
+
+ if (N == NULL || rng == NULL)
+ return -1;
+
+ /* get type */
+ if (len < 0) {
+ type = USE_BBS;
+ len = -len;
+ } else {
+ type = 0;
+ }
+
+ /* allow sizes between 2 and 512 bytes for a prime size */
+ if (len < 2 || len > 512) {
+ return -1;
+ }
+
+ /* allocate buffer to work with */
+ buf = XCALLOC(1, len, heap);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ do {
+#ifdef SHOW_GEN
+ printf(".");
+ fflush(stdout);
+#endif
+ /* generate value */
+ RNG_GenerateBlock(rng, buf, len);
+
+ /* munge bits */
+ buf[0] |= 0x80 | 0x40;
+ buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
+
+ /* load value */
+ if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
+ XFREE(buf, heap, DYNAMIC_TYPE_RSA);
+ return err;
+ }
+
+ /* test */
+ if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
+ XFREE(buf, heap, DYNAMIC_TYPE_RSA);
+ return err;
+ }
+ } while (res == MP_NO);
+
+#ifdef LTC_CLEAN_STACK
+ XMEMSET(buf, 0, len);
+#endif
+
+ XFREE(buf, heap, DYNAMIC_TYPE_RSA);
+ return 0;
+}
+
+
+/* Make an RSA key for size bits, with e specified, 65537 is a good e */
+int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
+{
+ mp_int p, q, tmp1, tmp2, tmp3;
+ int err;
+
+ if (key == NULL || rng == NULL)
+ return -1;
+
+ if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
+ return -1;
+
+ if (e < 3 || (e & 1) == 0)
+ return -1;
+
+ if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
+ return err;
+
+ err = mp_set_int(&tmp3, e);
+
+ /* make p */
+ if (err == MP_OKAY) {
+ do {
+ err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
+
+ if (err == MP_OKAY)
+ err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */
+
+ if (err == MP_OKAY)
+ err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */
+ } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes p-1 */
+ }
+
+ /* make q */
+ if (err == MP_OKAY) {
+ do {
+ err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
+
+ if (err == MP_OKAY)
+ err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */
+
+ if (err == MP_OKAY)
+ err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */
+ } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divdes q-1 */
+ }
+
+ if (err == MP_OKAY)
+ err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
+
+ if (err == MP_OKAY)
+ err = mp_init_multi(&key->dP, &key->dP, &key->u, NULL, NULL, NULL);
+
+ if (err == MP_OKAY)
+ err = mp_sub_d(&p, 1, &tmp2); /* tmp2 = p-1 */
+
+ if (err == MP_OKAY)
+ err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */
+
+ /* make key */
+ if (err == MP_OKAY)
+ err = mp_set_int(&key->e, e); /* key->e = e */
+
+ if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */
+ err = mp_invmod(&key->e, &tmp1, &key->d);
+
+ if (err == MP_OKAY)
+ err = mp_mul(&p, &q, &key->n); /* key->n = pq */
+
+ if (err == MP_OKAY)
+ err = mp_sub_d(&p, 1, &tmp1);
+
+ if (err == MP_OKAY)
+ err = mp_sub_d(&q, 1, &tmp2);
+
+ if (err == MP_OKAY)
+ err = mp_mod(&key->d, &tmp1, &key->dP);
+
+ if (err == MP_OKAY)
+ err = mp_mod(&key->d, &tmp2, &key->dQ);
+
+ if (err == MP_OKAY)
+ err = mp_invmod(&q, &p, &key->u);
+
+ if (err == MP_OKAY)
+ err = mp_copy(&p, &key->p);
+
+ if (err == MP_OKAY)
+ err = mp_copy(&q, &key->q);
+
+ if (err == MP_OKAY)
+ key->type = RSA_PRIVATE;
+
+ mp_clear(&tmp3);
+ mp_clear(&tmp2);
+ mp_clear(&tmp1);
+ mp_clear(&q);
+ mp_clear(&p);
+
+ if (err != MP_OKAY) {
+ FreeRsaKey(key);
+ return err;
+ }
+
+ return 0;
+}
+
+
+#endif /* CYASLS_KEY_GEN */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sha.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,198 @@
+/* sha.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "ctc_sha.h"
+#ifdef NO_INLINE
+ #include "misc.h"
+#else
+ #include "misc.c"
+#endif
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+void InitSha(Sha* sha)
+{
+ sha->digest[0] = 0x67452301L;
+ sha->digest[1] = 0xEFCDAB89L;
+ sha->digest[2] = 0x98BADCFEL;
+ sha->digest[3] = 0x10325476L;
+ sha->digest[4] = 0xC3D2E1F0L;
+
+ sha->buffLen = 0;
+ sha->loLen = 0;
+ sha->hiLen = 0;
+}
+
+#define blk0(i) (W[i] = sha->buffer[i])
+#define blk1(i) (W[i&15] = \
+ rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
+
+#define f1(x,y,z) (z^(x &(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+
+
+static void Transform(Sha* sha)
+{
+ word32 W[SHA_BLOCK_SIZE / sizeof(word32)];
+
+ /* Copy context->state[] to working vars */
+ word32 a = sha->digest[0];
+ word32 b = sha->digest[1];
+ word32 c = sha->digest[2];
+ word32 d = sha->digest[3];
+ word32 e = sha->digest[4];
+
+ /* nearly 1 K bigger in code size but 25% faster */
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ /* Add the working vars back into digest state[] */
+ sha->digest[0] += a;
+ sha->digest[1] += b;
+ sha->digest[2] += c;
+ sha->digest[3] += d;
+ sha->digest[4] += e;
+}
+
+
+static INLINE void AddLength(Sha* sha, word32 len)
+{
+ word32 tmp = sha->loLen;
+ if ( (sha->loLen += len) < tmp)
+ sha->hiLen++; /* carry low to high */
+}
+
+
+void ShaUpdate(Sha* sha, const byte* data, word32 len)
+{
+ /* do block size increments */
+ byte* local = (byte*)sha->buffer;
+
+ while (len) {
+ word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen);
+ XMEMCPY(&local[sha->buffLen], data, add);
+
+ sha->buffLen += add;
+ data += add;
+ len -= add;
+
+ if (sha->buffLen == SHA_BLOCK_SIZE) {
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseBytes(local, local, SHA_BLOCK_SIZE);
+ #endif
+ Transform(sha);
+ AddLength(sha, SHA_BLOCK_SIZE);
+ sha->buffLen = 0;
+ }
+ }
+}
+
+
+void ShaFinal(Sha* sha, byte* hash)
+{
+ byte* local = (byte*)sha->buffer;
+
+ AddLength(sha, sha->buffLen); /* before adding pads */
+
+ local[sha->buffLen++] = 0x80; /* add 1 */
+
+ /* pad with zeros */
+ if (sha->buffLen > SHA_PAD_SIZE) {
+ XMEMSET(&local[sha->buffLen], 0, SHA_BLOCK_SIZE - sha->buffLen);
+ sha->buffLen += SHA_BLOCK_SIZE - sha->buffLen;
+
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseBytes(local, local, SHA_BLOCK_SIZE);
+ #endif
+ Transform(sha);
+ sha->buffLen = 0;
+ }
+ XMEMSET(&local[sha->buffLen], 0, SHA_PAD_SIZE - sha->buffLen);
+
+ /* put lengths in bits */
+ sha->loLen = sha->loLen << 3;
+ sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) +
+ (sha->hiLen << 3);
+
+ /* store lengths */
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseBytes(local, local, SHA_BLOCK_SIZE);
+ #endif
+ /* ! length ordering dependent on digest endian type ! */
+ XMEMCPY(&local[SHA_PAD_SIZE], &sha->hiLen, sizeof(word32));
+ XMEMCPY(&local[SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32));
+
+ Transform(sha);
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE);
+ #endif
+ XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE);
+
+ InitSha(sha); /* reset state */
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sha256.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,206 @@
+/* sha256.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* code submitted by raphael.huck@efixo.com */
+
+
+
+#ifndef NO_SHA256
+
+#include "sha256.h"
+#ifdef NO_INLINE
+ #include "misc.h"
+#else
+ #include "misc.c"
+#endif
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+void InitSha256(Sha256* sha256)
+{
+ sha256->digest[0] = 0x6A09E667L;
+ sha256->digest[1] = 0xBB67AE85L;
+ sha256->digest[2] = 0x3C6EF372L;
+ sha256->digest[3] = 0xA54FF53AL;
+ sha256->digest[4] = 0x510E527FL;
+ sha256->digest[5] = 0x9B05688CL;
+ sha256->digest[6] = 0x1F83D9ABL;
+ sha256->digest[7] = 0x5BE0CD19L;
+
+ sha256->buffLen = 0;
+ sha256->loLen = 0;
+ sha256->hiLen = 0;
+}
+
+static const word32 K[64] = {
+ 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
+ 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
+ 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
+ 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
+ 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
+ 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
+ 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
+ 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
+ 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
+ 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
+ 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
+ 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
+ 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
+};
+
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S(x, n) rotrFixed(x, n)
+#define R(x, n) (((x)&0xFFFFFFFFL)>>(n))
+#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+#define RND(a,b,c,d,e,f,g,h,i) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+
+static void Transform(Sha256* sha256)
+{
+ word32 S[8], W[64], t0, t1;
+ int i;
+
+ /* Copy context->state[] to working vars */
+ for (i = 0; i < 8; i++)
+ S[i] = sha256->digest[i];
+
+ for (i = 0; i < 16; i++)
+ W[i] = sha256->buffer[i];
+
+ for (i = 16; i < 64; i++)
+ W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
+
+ for (i = 0; i < 64; i += 8) {
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
+ }
+
+ /* Add the working vars back into digest state[] */
+ for (i = 0; i < 8; i++) {
+ sha256->digest[i] += S[i];
+ }
+}
+
+
+static INLINE void AddLength(Sha256* sha256, word32 len)
+{
+ word32 tmp = sha256->loLen;
+ if ( (sha256->loLen += len) < tmp)
+ sha256->hiLen++; /* carry low to high */
+}
+
+
+void Sha256Update(Sha256* sha256, const byte* data, word32 len)
+{
+ /* do block size increments */
+ byte* local = (byte*)sha256->buffer;
+
+ while (len) {
+ word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen);
+ XMEMCPY(&local[sha256->buffLen], data, add);
+
+ sha256->buffLen += add;
+ data += add;
+ len -= add;
+
+ if (sha256->buffLen == SHA256_BLOCK_SIZE) {
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseBytes(local, local, SHA256_BLOCK_SIZE);
+ #endif
+ Transform(sha256);
+ AddLength(sha256, SHA256_BLOCK_SIZE);
+ sha256->buffLen = 0;
+ }
+ }
+}
+
+
+void Sha256Final(Sha256* sha256, byte* hash)
+{
+ byte* local = (byte*)sha256->buffer;
+
+ AddLength(sha256, sha256->buffLen); /* before adding pads */
+
+ local[sha256->buffLen++] = 0x80; /* add 1 */
+
+ /* pad with zeros */
+ if (sha256->buffLen > SHA256_PAD_SIZE) {
+ XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen);
+ sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen;
+
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseBytes(local, local, SHA256_BLOCK_SIZE);
+ #endif
+ Transform(sha256);
+ sha256->buffLen = 0;
+ }
+ XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen);
+
+ /* put lengths in bits */
+ sha256->loLen = sha256->loLen << 3;
+ sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) +
+ (sha256->hiLen << 3);
+
+ /* store lengths */
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseBytes(local, local, SHA256_BLOCK_SIZE);
+ #endif
+ /* ! length ordering dependent on digest endian type ! */
+ XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
+ XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
+ sizeof(word32));
+
+ Transform(sha256);
+ #ifdef LITTLE_ENDIAN_ORDER
+ ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE);
+ #endif
+ XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE);
+
+ InitSha256(sha256); /* reset state */
+}
+
+
+#endif /* NO_SHA256 */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sha256.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,69 @@
+/* sha256.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* code submitted by raphael.huck@efixo.com */
+
+
+#ifndef NO_SHA256
+
+#ifndef CTAO_CRYPT_SHA256_H
+#define CTAO_CRYPT_SHA256_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/* in bytes */
+enum {
+ SHA256 = 2, /* hash type unique */
+ SHA256_BLOCK_SIZE = 64,
+ SHA256_DIGEST_SIZE = 32,
+ SHA256_PAD_SIZE = 56
+};
+
+
+/* Sha256 digest */
+typedef struct Sha256 {
+ word32 buffLen; /* in bytes */
+ word32 loLen; /* length in bytes */
+ word32 hiLen; /* length in bytes */
+ word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)];
+ word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)];
+} Sha256;
+
+
+void InitSha256(Sha256*);
+void Sha256Update(Sha256*, const byte*, word32);
+void Sha256Final(Sha256*, byte*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_SHA256_H */
+#endif /* NO_SHA256 */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sha512.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,65 @@
+/* sha512.h
+ *
+ * Copyright (C) 2006-2010 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifdef CYASSL_SHA512
+
+#ifndef CTAO_CRYPT_SHA512_H
+#define CTAO_CRYPT_SHA512_H
+
+#include "types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/* in bytes */
+enum {
+ SHA512 = 4, /* hash type unique */
+ SHA512_BLOCK_SIZE = 128,
+ SHA512_DIGEST_SIZE = 64,
+ SHA512_PAD_SIZE = 112
+};
+
+
+/* Sha512 digest */
+typedef struct Sha512 {
+ word32 buffLen; /* in bytes */
+ word32 loLen; /* length in bytes */
+ word32 hiLen; /* length in bytes */
+ word64 digest[SHA512_DIGEST_SIZE / sizeof(word64)];
+ word64 buffer[SHA512_BLOCK_SIZE / sizeof(word64)];
+} Sha512;
+
+
+void InitSha512(Sha512*);
+void Sha512Update(Sha512*, const byte*, word32);
+void Sha512Final(Sha512*, byte*);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif /* CTAO_CRYPT_SHA512_H */
+#endif /* CYASSL_SHA512 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ssl.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,3415 @@
+/* ssl.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "ssl.h"
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#include "coding.h"
+
+#ifdef OPENSSL_EXTRA
+ /* openssl headers begin */
+ #include "evp.h"
+ #include "hmac.h"
+ #include "crypto.h"
+ #include "des.h"
+ /* openssl headers end, cyassl internal headers next */
+ #include "ctc_hmac.h"
+ #include "random.h"
+ #include "des3.h"
+ #include "ctc_md4.h"
+ #include "coding.h"
+#endif
+
+#ifdef HAVE_ERRNO_H
+ #include <errno.h>
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
+{
+ SSL_CTX* ctx = (SSL_CTX*) XMALLOC(sizeof(SSL_CTX), 0, DYNAMIC_TYPE_CTX);
+ if (ctx)
+ InitSSL_Ctx(ctx, method);
+
+ return ctx;
+}
+
+
+void SSL_CTX_free(SSL_CTX* ctx)
+{
+ if (ctx)
+ FreeSSL_Ctx(ctx);
+}
+
+
+SSL* SSL_new(SSL_CTX* ctx)
+{
+
+ SSL* ssl = (SSL*) XMALLOC(sizeof(SSL), ctx->heap, DYNAMIC_TYPE_SSL);
+ if (ssl)
+ if (InitSSL(ssl, ctx) < 0) {
+ FreeSSL(ssl);
+ ssl = 0;
+ }
+
+ return ssl;
+}
+
+
+void SSL_free(SSL* ssl)
+{
+ CYASSL_ENTER("SSL_free");
+ if (ssl)
+ FreeSSL(ssl);
+ CYASSL_LEAVE("SSL_free", 0);
+}
+
+
+int SSL_set_fd(SSL* ssl, int fd)
+{
+ ssl->rfd = fd; /* not used directly to allow IO callbacks */
+ ssl->wfd = fd;
+
+ ssl->IOCB_ReadCtx = &ssl->rfd;
+ ssl->IOCB_WriteCtx = &ssl->wfd;
+
+ return SSL_SUCCESS;
+}
+
+
+int SSL_get_fd(const SSL* ssl)
+{
+ return ssl->rfd;
+}
+
+
+int CyaSSL_negotiate(SSL* ssl)
+{
+ int err = -1;
+
+#ifndef NO_CYASSL_SERVER
+ if (ssl->options.side == SERVER_END)
+ err = SSL_accept(ssl);
+#endif
+
+#ifndef NO_CYASSL_CLIENT
+ if (ssl->options.side == CLIENT_END)
+ err = SSL_connect(ssl);
+#endif
+
+ if (err == SSL_SUCCESS)
+ return 0;
+ else
+ return err;
+}
+
+
+int SSL_write(SSL* ssl, const void* buffer, int sz)
+{
+ int ret;
+
+ CYASSL_ENTER("SSL_write()");
+
+#ifdef HAVE_ERRNO_H
+ errno = 0;
+#endif
+
+ ret = SendData(ssl, buffer, sz);
+
+ CYASSL_LEAVE("SSL_write()", ret);
+
+ if (ret < 0)
+ return SSL_FATAL_ERROR;
+ else
+ return ret;
+}
+
+
+int SSL_read(SSL* ssl, void* buffer, int sz)
+{
+ int ret;
+
+ CYASSL_ENTER("SSL_read()");
+
+#ifdef HAVE_ERRNO_H
+ errno = 0;
+#endif
+
+ ret = ReceiveData(ssl, (byte*)buffer, min(sz, OUTPUT_RECORD_SIZE));
+
+ CYASSL_LEAVE("SSL_read()", ret);
+
+ if (ret < 0)
+ return SSL_FATAL_ERROR;
+ else
+ return ret;
+}
+
+
+int SSL_shutdown(SSL* ssl)
+{
+ CYASSL_ENTER("SSL_shutdown()");
+
+ if (ssl->options.quietShutdown) {
+ CYASSL_MSG("quiet shutdown, no close notify sent");
+ return 0;
+ }
+
+ /* try to send close notify, not an error if can't */
+ if (!ssl->options.isClosed && !ssl->options.connReset &&
+ !ssl->options.sentNotify) {
+ ssl->error = SendAlert(ssl, alert_warning, close_notify);
+ if (ssl->error < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.sentNotify = 1; /* don't send close_notify twice */
+ }
+
+ CYASSL_LEAVE("SSL_shutdown()", ssl->error);
+
+ ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */
+
+ return 0;
+}
+
+
+int SSL_get_error(SSL* ssl, int dummy)
+{
+ if (ssl->error == WANT_READ)
+ return SSL_ERROR_WANT_READ; /* convert to OpenSSL type */
+ else if (ssl->error == WANT_WRITE)
+ return SSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */
+ else if (ssl->error == ZERO_RETURN)
+ return SSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */
+ return ssl->error;
+}
+
+
+int SSL_want_read(SSL* ssl)
+{
+ if (ssl->error == WANT_READ)
+ return 1;
+
+ return 0;
+}
+
+
+int SSL_want_write(SSL* ssl)
+{
+ if (ssl->error == WANT_WRITE)
+ return 1;
+
+ return 0;
+}
+
+
+char* ERR_error_string(unsigned long errNumber, char* buffer)
+{
+ static char* msg = "Please supply a buffer for error string";
+
+ if (buffer) {
+ SetErrorString(errNumber, buffer);
+ return buffer;
+ }
+
+ return msg;
+}
+
+
+void ERR_error_string_n(unsigned long e, char* buf, size_t len)
+{
+ if (len) ERR_error_string(e, buf);
+}
+
+
+#ifndef NO_FILESYSTEM
+
+void ERR_print_errors_fp(FILE* fp, int err)
+{
+ char buffer[MAX_ERROR_SZ + 1];
+
+ SetErrorString(err, buffer);
+ fprintf(fp, "%s", buffer);
+}
+
+#endif
+
+
+int SSL_pending(SSL* ssl)
+{
+ return ssl->buffers.clearOutputBuffer.length;
+}
+
+
+/* owns der */
+static int AddCA(SSL_CTX* ctx, buffer der)
+{
+ word32 ret;
+ DecodedCert cert;
+ Signer* signer = 0;
+
+ InitDecodedCert(&cert, der.buffer, ctx->heap);
+ ret = ParseCert(&cert, der.length, CA_TYPE, ctx->verifyPeer, 0);
+
+ if (ret == 0) {
+ /* take over signer parts */
+ signer = MakeSigner(ctx->heap);
+ if (!signer)
+ ret = MEMORY_ERROR;
+ else {
+ signer->keyOID = cert.keyOID;
+ signer->publicKey = cert.publicKey;
+ signer->pubKeySize = cert.pubKeySize;
+ signer->name = cert.subjectCN;
+ XMEMCPY(signer->hash, cert.subjectHash, SHA_DIGEST_SIZE);
+
+ cert.publicKey = 0; /* don't free here */
+ cert.subjectCN = 0;
+
+ signer->next = ctx->caList;
+ ctx->caList = signer; /* takes ownership */
+ }
+ }
+
+ FreeDecodedCert(&cert);
+ XFREE(der.buffer, ctx->heap, DYNAMIC_TYPE_CA);
+
+ if (ret == 0) return SSL_SUCCESS;
+ return ret;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+ /* basic config gives a cache with 33 sessions, adequate for clients and
+ embedded servers
+
+ BIG_SESSION_CACHE allows 1055 sessions, adequate for servers that aren't
+ under heavy load, basically allows 200 new sessions per minute
+
+ HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
+ allows over 13,000 new sessions per minute or over 200 new sessions per
+ second
+ */
+ #ifdef HUGE_SESSION_CACHE
+ #define SESSIONS_PER_ROW 11
+ #define SESSION_ROWS 5981
+ #elif defined(BIG_SESSION_CACHE)
+ #define SESSIONS_PER_ROW 5
+ #define SESSION_ROWS 211
+ #else
+ #define SESSIONS_PER_ROW 3
+ #define SESSION_ROWS 11
+ #endif
+
+ typedef struct SessionRow {
+ int nextIdx; /* where to place next one */
+ int totalCount; /* sessions ever on this row */
+ SSL_SESSION Sessions[SESSIONS_PER_ROW];
+ } SessionRow;
+
+ static SessionRow SessionCache[SESSION_ROWS];
+
+ static CyaSSL_Mutex mutex; /* SessionCache mutex */
+
+#endif /* NO_SESSION_CACHE */
+
+
+ static int PemToDer(const unsigned char* buff, long sz, int type,
+ buffer* der, void* heap, EncryptedInfo* info)
+ {
+ char header[PEM_LINE_LEN];
+ char footer[PEM_LINE_LEN];
+ char* headerEnd;
+ char* footerEnd;
+ long neededSz;
+ int pkcs8 = 0;
+ int dynamicType;
+
+ if (type == CERT_TYPE || type == CA_TYPE) {
+ XSTRNCPY(header, "-----BEGIN CERTIFICATE-----", sizeof(header));
+ XSTRNCPY(footer, "-----END CERTIFICATE-----", sizeof(footer));
+ dynamicType = (type == CA_TYPE) ? DYNAMIC_TYPE_CA :
+ DYNAMIC_TYPE_CERT;
+ } else {
+ XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header));
+ XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----", sizeof(footer));
+ dynamicType = DYNAMIC_TYPE_KEY;
+ }
+
+ /* find header */
+ headerEnd = XSTRSTR((char*)buff, header);
+ if (!headerEnd && type == PRIVATEKEY_TYPE) { /* may be pkcs8 */
+ XSTRNCPY(header, "-----BEGIN PRIVATE KEY-----", sizeof(header));
+ XSTRNCPY(footer, "-----END PRIVATE KEY-----", sizeof(footer));
+
+ headerEnd = XSTRSTR((char*)buff, header);
+ if (headerEnd)
+ pkcs8 = 1;
+ /*
+ else
+ maybe encrypted "-----BEGIN ENCRYPTED PRIVATE KEY-----"
+ */
+ }
+ if (!headerEnd)
+ return SSL_BAD_FILE;
+ headerEnd += XSTRLEN(header);
+
+ /* get next line */
+ if (headerEnd[0] == '\n')
+ headerEnd++;
+ else if (headerEnd[1] == '\n')
+ headerEnd += 2;
+ else
+ return SSL_BAD_FILE;
+
+#ifdef OPENSSL_EXTRA
+ {
+ /* remove encrypted header if there */
+ char encHeader[] = "Proc-Type";
+ char* line = XSTRSTR((char*)buff, encHeader);
+ if (line) {
+ char* newline;
+ char* finish;
+ char* start = XSTRSTR(line, "DES");
+
+ if (!start)
+ start = XSTRSTR(line, "AES");
+
+ if (!start) return SSL_BAD_FILE;
+ if (!info) return SSL_BAD_FILE;
+
+ finish = XSTRSTR(start, ",");
+
+ if (start && finish && (start < finish)) {
+ newline = XSTRSTR(finish, "\r");
+
+ XMEMCPY(info->name, start, finish - start);
+ info->name[finish - start] = 0;
+ XMEMCPY(info->iv, finish + 1, sizeof(info->iv));
+
+ if (!newline) newline = XSTRSTR(finish, "\n");
+ if (newline && (newline > finish)) {
+ info->ivSz = (word32)(newline - (finish + 1));
+ info->set = 1;
+ }
+ else
+ return SSL_BAD_FILE;
+ }
+ else
+ return SSL_BAD_FILE;
+
+ /* eat blank line */
+ while (*newline == '\r' || *newline == '\n')
+ newline++;
+ headerEnd = newline;
+ }
+ }
+#endif /* OPENSSL_EXTRA */
+
+ /* find footer */
+ footerEnd = XSTRSTR((char*)buff, footer);
+ if (!footerEnd) return SSL_BAD_FILE;
+
+ /* set up der buffer */
+ neededSz = (long)(footerEnd - headerEnd);
+ if (neededSz > sz || neededSz < 0) return SSL_BAD_FILE;
+ der->buffer = (byte*) XMALLOC(neededSz, heap, dynamicType);
+ if (!der->buffer) return MEMORY_ERROR;
+ der->length = neededSz;
+
+ if (Base64Decode((byte*)headerEnd, neededSz, der->buffer,
+ &der->length) < 0)
+ return SSL_BAD_FILE;
+
+ if (pkcs8)
+ return ToTraditional(der->buffer, der->length);
+
+ /* not full support yet
+ if (pkcs8Enc)
+ return ToTraditionalEnc(der->buffer, der->length);
+ */
+
+ return 0;
+ }
+
+
+ static int ProcessBuffer(SSL_CTX* ctx, const unsigned char* buff,
+ long sz, int format, int type)
+ {
+ EncryptedInfo info;
+ buffer der; /* holds DER or RAW (for NTRU */
+ int dynamicType;
+
+ info.set = 0;
+ der.buffer = 0;
+
+ if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM
+ && format != SSL_FILETYPE_RAW)
+ return SSL_BAD_FILETYPE;
+
+ if (type == CA_TYPE)
+ dynamicType = DYNAMIC_TYPE_CA;
+ else if (type == CERT_TYPE)
+ dynamicType = DYNAMIC_TYPE_CERT;
+ else
+ dynamicType = DYNAMIC_TYPE_KEY;
+
+ if (format == SSL_FILETYPE_PEM) {
+ if (PemToDer(buff, sz, type, &der, ctx->heap, &info) < 0) {
+ XFREE(der.buffer, ctx->heap, dynamicType);
+ return SSL_BAD_FILE;
+ }
+ }
+ else { /* ASN1 (DER) or RAW (NTRU) */
+ der.buffer = (byte*) XMALLOC(sz, ctx->heap, dynamicType);
+ if (!der.buffer) return MEMORY_ERROR;
+ XMEMCPY(der.buffer, buff, sz);
+ der.length = sz;
+ }
+
+#ifdef OPENSSL_EXTRA
+ if (info.set) {
+ /* decrypt */
+ char password[80];
+ int passwordSz;
+
+ byte key[AES_256_KEY_SIZE];
+ byte iv[AES_IV_SIZE];
+
+ if (!ctx->passwd_cb) return -1;
+
+ /* use file's salt for key derivation, hex decode first */
+ if (Base16Decode(info.iv, info.ivSz, info.iv, &info.ivSz) != 0)
+ return -1;
+
+ passwordSz = ctx->passwd_cb(password, sizeof(password), 0,
+ ctx->userdata);
+ if (EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password,
+ passwordSz, 1, key, iv) <= 0)
+ return -1;
+
+ if (XSTRNCMP(info.name, "DES-CBC", 7) == 0) {
+ Des des;
+ Des_SetKey(&des, key, info.iv, DES_DECRYPTION);
+ Des_CbcDecrypt(&des, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "DES-EDE3-CBC", 13) == 0) {
+ Des3 des;
+ Des3_SetKey(&des, key, info.iv, DES_DECRYPTION);
+ Des3_CbcDecrypt(&des, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "AES-128-CBC", 13) == 0) {
+ Aes aes;
+ AesSetKey(&aes, key, AES_128_KEY_SIZE, info.iv, AES_DECRYPTION);
+ AesCbcDecrypt(&aes, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "AES-192-CBC", 13) == 0) {
+ Aes aes;
+ AesSetKey(&aes, key, AES_192_KEY_SIZE, info.iv, AES_DECRYPTION);
+ AesCbcDecrypt(&aes, der.buffer, der.buffer, der.length);
+ }
+ else if (XSTRNCMP(info.name, "AES-256-CBC", 13) == 0) {
+ Aes aes;
+ AesSetKey(&aes, key, AES_256_KEY_SIZE, info.iv, AES_DECRYPTION);
+ AesCbcDecrypt(&aes, der.buffer, der.buffer, der.length);
+ }
+ else
+ return SSL_BAD_FILE;
+ }
+#endif /* OPENSSL_EXTRA */
+
+ if (type == CA_TYPE)
+ return AddCA(ctx, der); /* takes der over */
+ else if (type == CERT_TYPE) {
+ if (ctx->certificate.buffer)
+ XFREE(ctx->certificate.buffer, ctx->heap, dynamicType);
+ ctx->certificate = der; /* takes der over */
+ }
+ else if (type == PRIVATEKEY_TYPE) {
+ if (ctx->privateKey.buffer)
+ XFREE(ctx->privateKey.buffer, ctx->heap, dynamicType);
+ ctx->privateKey = der; /* takes der over */
+ }
+ else {
+ XFREE(der.buffer, ctx->heap, dynamicType);
+ return SSL_BAD_CERTTYPE;
+ }
+
+ if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) {
+ /* make sure RSA key can be used */
+ RsaKey key;
+ word32 idx = 0;
+
+ InitRsaKey(&key, 0);
+ if (RsaPrivateKeyDecode(der.buffer, &idx, &key, der.length) != 0) {
+ FreeRsaKey(&key);
+ return SSL_BAD_FILE;
+ }
+
+ FreeRsaKey(&key);
+ }
+
+ return SSL_SUCCESS;
+ }
+
+
+#ifndef NO_FILESYSTEM
+
+#ifndef MICRIUM
+ #define XFILE FILE
+ #define XFOPEN fopen
+ #define XFSEEK fseek
+ #define XFTELL ftell
+ #define XREWIND rewind
+ #define XFREAD fread
+ #define XFCLOSE fclose
+ #define XSEEK_END SEEK_END
+#else
+ #include <fs.h>
+ #define XFILE FS_FILE
+ #define XFOPEN fs_fopen
+ #define XFSEEK fs_fseek
+ #define XFTELL fs_ftell
+ #define XREWIND fs_rewind
+ #define XFREAD fs_fread
+ #define XFCLOSE fs_fclose
+ #define XSEEK_END FS_SEEK_END
+#endif
+
+static int ProcessFile(SSL_CTX* ctx, const char* fname, int format, int type)
+{
+ byte staticBuffer[FILE_BUFFER_SIZE];
+ byte* buffer = staticBuffer;
+ int dynamic = 0;
+ int ret;
+ long sz = 0;
+ XFILE* file = XFOPEN(fname, "rb");
+
+ if (!file) return SSL_BAD_FILE;
+ XFSEEK(file, 0, XSEEK_END);
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz > sizeof(staticBuffer)) {
+ buffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE);
+ if (buffer == NULL) {
+ XFCLOSE(file);
+ return SSL_BAD_FILE;
+ }
+ dynamic = 1;
+ }
+
+ if ( (ret = XFREAD(buffer, sz, 1, file)) < 0)
+ ret = SSL_BAD_FILE;
+ else
+ ret = ProcessBuffer(ctx, buffer, sz, format, type);
+
+ XFCLOSE(file);
+ if (dynamic) XFREE(buffer, ctx->heap, DYNAMIC_TYPE_FILE);
+
+ return ret;
+}
+
+
+/* just one for now TODO: add dir support from path */
+int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
+ const char* path)
+{
+ if (ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+#ifdef CYASSL_DER_LOAD
+
+/* Add format parameter to allow DER load of CA files */
+int CyaSSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file, int format)
+{
+ if (ProcessFile(ctx, file, format, CA_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+#endif /* CYASSL_DER_LOAD */
+
+
+#ifdef CYASSL_CERT_GEN
+
+/* load pem cert from file into der buffer, return der size or error */
+int CyaSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
+{
+ byte staticBuffer[FILE_BUFFER_SIZE];
+ byte* fileBuf = staticBuffer;
+ int dynamic = 0;
+ int ret;
+ long sz = 0;
+ XFILE* file = XFOPEN(fileName, "rb");
+ EncryptedInfo info;
+ buffer converted;
+
+ converted.buffer = 0;
+
+ if (!file) return SSL_BAD_FILE;
+ XFSEEK(file, 0, XSEEK_END);
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz > sizeof(staticBuffer)) {
+ fileBuf = (byte*) XMALLOC(sz, 0, DYNAMIC_TYPE_FILE);
+ if (fileBuf == NULL) {
+ XFCLOSE(file);
+ return SSL_BAD_FILE;
+ }
+ dynamic = 1;
+ }
+
+ if ( (ret = XFREAD(fileBuf, sz, 1, file)) < 0)
+ ret = SSL_BAD_FILE;
+ else
+ ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, &info);
+
+ if (ret == 0) {
+ if (converted.length < derSz) {
+ memcpy(derBuf, converted.buffer, converted.length);
+ ret = converted.length;
+ }
+ else
+ ret = BUFFER_E;
+ }
+
+ XFREE(converted.buffer, 0, DYNAMIC_TYPE_CA);
+ if (dynamic)
+ XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE);
+ XFCLOSE(file);
+
+ return ret;
+}
+
+#endif /* CYASSL_CERT_GEN */
+
+
+int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format)
+{
+ if (ProcessFile(ctx, file, format, CERT_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format)
+{
+ if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+int SSL_CTX_use_certificate_chain_file(SSL_CTX* ctx, const char* file)
+{
+ /* add first to ctx, all tested implementations support this */
+ if (ProcessFile(ctx, file, SSL_FILETYPE_PEM, CERT_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+}
+
+
+#ifdef HAVE_NTRU
+
+int CyaSSL_CTX_use_NTRUPrivateKey_file(SSL_CTX* ctx, const char* file)
+{
+ if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE)
+ == SSL_SUCCESS) {
+ ctx->haveNTRU = 1;
+ return SSL_SUCCESS;
+ }
+
+ return SSL_FAILURE;
+}
+
+#endif /* HAVE_NTRU */
+
+
+
+#ifdef OPENSSL_EXTRA
+
+ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX* ctx,const char* file,int format)
+ {
+ if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE) == SSL_SUCCESS)
+ return SSL_SUCCESS;
+
+ return SSL_FAILURE;
+ }
+
+#endif /* OPENSSL_EXTRA */
+
+#endif /* NO_FILESYSTEM */
+
+
+void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback vc)
+{
+ if (mode & SSL_VERIFY_PEER) {
+ ctx->verifyPeer = 1;
+ ctx->verifyNone = 0; /* in case perviously set */
+ }
+
+ if (mode == SSL_VERIFY_NONE) {
+ ctx->verifyNone = 1;
+ ctx->verifyPeer = 0; /* in case previously set */
+ }
+
+ if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ ctx->failNoCert = 1;
+
+ ctx->verifyCallback = vc;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+SSL_SESSION* SSL_get_session(SSL* ssl)
+{
+ return GetSession(ssl, 0);
+}
+
+
+int SSL_set_session(SSL* ssl, SSL_SESSION* session)
+{
+ if (session)
+ return SetSession(ssl, session);
+
+ return SSL_FAILURE;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+void SSL_load_error_strings(void) /* compatibility only */
+{}
+
+
+int SSL_library_init(void)
+{
+ if (InitCyaSSL() == 0)
+ return SSL_SUCCESS;
+ else
+ return -1;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+/* on by default if built in but allow user to turn off */
+long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode)
+{
+ if (mode == SSL_SESS_CACHE_OFF)
+ ctx->sessionCacheOff = 1;
+
+ if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR)
+ ctx->sessionCacheFlushOff = 1;
+
+ return SSL_SUCCESS;
+}
+
+#endif /* NO_SESSION_CACHE */
+
+
+int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
+{
+ if (SetCipherList(ctx, list))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+/* client only parts */
+#ifndef NO_CYASSL_CLIENT
+
+ SSL_METHOD* SSLv3_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeSSLv3());
+ return method;
+ }
+
+ #ifdef CYASSL_DTLS
+ SSL_METHOD* DTLSv1_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeDTLSv1());
+ return method;
+ }
+ #endif
+
+
+ /* please see note at top of README if you get an error from connect */
+ int SSL_connect(SSL* ssl)
+ {
+ int neededState;
+
+ CYASSL_ENTER("SSL_connect()");
+
+ #ifdef HAVE_ERRNO_H
+ errno = 0;
+ #endif
+
+ if (ssl->options.side != CLIENT_END) {
+ CYASSL_ERROR(ssl->error = SIDE_ERROR);
+ return SSL_FATAL_ERROR;
+ }
+
+ #ifdef CYASSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR &&
+ ssl->version.minor == DTLS_MINOR) {
+ ssl->options.dtls = 1;
+ ssl->options.tls = 1;
+ ssl->options.tls1_1 = 1;
+ }
+ #endif
+
+ if (ssl->buffers.outputBuffer.length > 0) {
+ if ( (ssl->error = SendBuffered(ssl)) == 0) {
+ ssl->options.connectState++;
+ CYASSL_MSG("connect state: Advanced from buffered send");
+ }
+ else {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+
+ switch (ssl->options.connectState) {
+
+ case CONNECT_BEGIN :
+ /* always send client hello first */
+ if ( (ssl->error = SendClientHello(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.connectState = CLIENT_HELLO_SENT;
+ CYASSL_MSG("connect state: CLIENT_HELLO_SENT");
+
+ case CLIENT_HELLO_SENT :
+ neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE :
+ SERVER_HELLODONE_COMPLETE;
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming)
+ neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+ #endif
+ /* get response */
+ while (ssl->options.serverState < neededState) {
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ /* if resumption failed, reset needed state */
+ else if (neededState == SERVER_FINISHED_COMPLETE)
+ if (!ssl->options.resuming) {
+ if (!ssl->options.dtls)
+ neededState = SERVER_HELLODONE_COMPLETE;
+ else
+ neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE;
+ }
+ }
+
+ ssl->options.connectState = HELLO_AGAIN;
+ CYASSL_MSG("connect state: HELLO_AGAIN");
+
+ case HELLO_AGAIN :
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming) {
+ /* re-init hashes, exclude first hello and verify request */
+ InitMd5(&ssl->hashMd5);
+ InitSha(&ssl->hashSha);
+ if ( (ssl->error = SendClientHello(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+ #endif
+
+ ssl->options.connectState = HELLO_AGAIN_REPLY;
+ CYASSL_MSG("connect state: HELLO_AGAIN_REPLY");
+
+ case HELLO_AGAIN_REPLY :
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ neededState = ssl->options.resuming ?
+ SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE;
+
+ /* get response */
+ while (ssl->options.serverState < neededState) {
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ /* if resumption failed, reset needed state */
+ else if (neededState == SERVER_FINISHED_COMPLETE)
+ if (!ssl->options.resuming)
+ neededState = SERVER_HELLODONE_COMPLETE;
+ }
+ }
+ #endif
+
+ ssl->options.connectState = FIRST_REPLY_DONE;
+ CYASSL_MSG("connect state: FIRST_REPLY_DONE");
+
+ case FIRST_REPLY_DONE :
+ if (ssl->options.sendVerify)
+ if ( (ssl->error = SendCertificate(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = FIRST_REPLY_FIRST;
+ CYASSL_MSG("connect state: FIRST_REPLY_FIRST");
+
+ case FIRST_REPLY_FIRST :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = FIRST_REPLY_SECOND;
+ CYASSL_MSG("connect state: FIRST_REPLY_SECOND");
+
+ case FIRST_REPLY_SECOND :
+ if (ssl->options.sendVerify)
+ if ( (ssl->error = SendCertificateVerify(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.connectState = FIRST_REPLY_THIRD;
+ CYASSL_MSG("connect state: FIRST_REPLY_THIRD");
+
+ case FIRST_REPLY_THIRD :
+ if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.connectState = FIRST_REPLY_FOURTH;
+ CYASSL_MSG("connect state: FIRST_REPLY_FOURTH");
+
+ case FIRST_REPLY_FOURTH :
+ if ( (ssl->error = SendFinished(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = FINISHED_DONE;
+ CYASSL_MSG("connect state: FINISHED_DONE");
+
+ case FINISHED_DONE :
+ /* get response */
+ while (ssl->options.serverState < SERVER_FINISHED_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.connectState = SECOND_REPLY_DONE;
+ CYASSL_MSG("connect state: SECOND_REPLY_DONE");
+
+ case SECOND_REPLY_DONE:
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+ CYASSL_LEAVE("SSL_connect()", SSL_SUCCESS);
+ return SSL_SUCCESS;
+
+ default:
+ CYASSL_MSG("Unknown connect state ERROR");
+ return SSL_FATAL_ERROR; /* unknown connect state */
+ }
+ }
+
+#endif /* NO_CYASSL_CLIENT */
+
+
+/* server only parts */
+#ifndef NO_CYASSL_SERVER
+
+ SSL_METHOD* SSLv3_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeSSLv3());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ #ifdef CYASSL_DTLS
+ SSL_METHOD* DTLSv1_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeDTLSv1());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+ #endif
+
+
+ int SSL_accept(SSL* ssl)
+ {
+ CYASSL_ENTER("SSL_accept()");
+
+ #ifdef HAVE_ERRNO_H
+ errno = 0;
+ #endif
+
+ if (ssl->options.side != SERVER_END) {
+ CYASSL_ERROR(ssl->error = SIDE_ERROR);
+ return SSL_FATAL_ERROR;
+ }
+
+ #ifdef CYASSL_DTLS
+ if (ssl->version.major == DTLS_MAJOR &&
+ ssl->version.minor == DTLS_MINOR) {
+ ssl->options.dtls = 1;
+ ssl->options.tls = 1;
+ ssl->options.tls1_1 = 1;
+ }
+ #endif
+
+ if (ssl->buffers.outputBuffer.length > 0) {
+ if ( (ssl->error = SendBuffered(ssl)) == 0) {
+ ssl->options.acceptState++;
+ CYASSL_MSG("accept state: Advanced from buffered send");
+ }
+ else {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+
+ switch (ssl->options.acceptState) {
+
+ case ACCEPT_BEGIN :
+ /* get response */
+ while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE;
+ CYASSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE");
+
+ case ACCEPT_CLIENT_HELLO_DONE :
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming)
+ if ( (ssl->error = SendHelloVerifyRequest(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ #endif
+ ssl->options.acceptState = HELLO_VERIFY_SENT;
+ CYASSL_MSG("accept state HELLO_VERIFY_SENT");
+
+ case HELLO_VERIFY_SENT:
+ #ifdef CYASSL_DTLS
+ if (ssl->options.dtls && !ssl->options.resuming) {
+ ssl->options.clientState = NULL_STATE; /* get again */
+ /* re-init hashes, exclude first hello and verify request */
+ InitMd5(&ssl->hashMd5);
+ InitSha(&ssl->hashSha);
+
+ while (ssl->options.clientState < CLIENT_HELLO_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+ #endif
+ ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
+ CYASSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
+
+ case ACCEPT_FIRST_REPLY_DONE :
+ if ( (ssl->error = SendServerHello(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = SERVER_HELLO_SENT;
+ CYASSL_MSG("accept state SERVER_HELLO_SENT");
+
+ case SERVER_HELLO_SENT :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendCertificate(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = CERT_SENT;
+ CYASSL_MSG("accept state CERT_SENT");
+
+ case CERT_SENT :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = KEY_EXCHANGE_SENT;
+ CYASSL_MSG("accept state KEY_EXCHANGE_SENT");
+
+ case KEY_EXCHANGE_SENT :
+ if (!ssl->options.resuming)
+ if (ssl->options.verifyPeer)
+ if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = CERT_REQ_SENT;
+ CYASSL_MSG("accept state CERT_REQ_SENT");
+
+ case CERT_REQ_SENT :
+ if (!ssl->options.resuming)
+ if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = SERVER_HELLO_DONE;
+ CYASSL_MSG("accept state SERVER_HELLO_DONE");
+
+ case SERVER_HELLO_DONE :
+ if (!ssl->options.resuming) {
+ while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ }
+ ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE;
+ CYASSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
+
+ case ACCEPT_SECOND_REPLY_DONE :
+ if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+ ssl->options.acceptState = CHANGE_CIPHER_SENT;
+ CYASSL_MSG("accept state CHANGE_CIPHER_SENT");
+
+ case CHANGE_CIPHER_SENT :
+ if ( (ssl->error = SendFinished(ssl)) != 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.acceptState = ACCEPT_FINISHED_DONE;
+ CYASSL_MSG("accept state ACCEPT_FINISHED_DONE");
+
+ case ACCEPT_FINISHED_DONE :
+ if (ssl->options.resuming)
+ while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE)
+ if ( (ssl->error = ProcessReply(ssl)) < 0) {
+ CYASSL_ERROR(ssl->error);
+ return SSL_FATAL_ERROR;
+ }
+
+ ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE;
+ CYASSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE");
+
+ case ACCEPT_THIRD_REPLY_DONE :
+ if (ssl->buffers.inputBuffer.dynamicFlag)
+ ShrinkInputBuffer(ssl, NO_FORCED_FREE);
+ CYASSL_LEAVE("SSL_accept()", SSL_SUCCESS);
+ return SSL_SUCCESS;
+
+ default :
+ CYASSL_MSG("Unknown accept state ERROR");
+ return SSL_FATAL_ERROR;
+ }
+ }
+
+#endif /* NO_CYASSL_SERVER */
+
+
+int InitCyaSSL(void)
+{
+ if (InitMutex(&mutex) == 0)
+ return 0;
+ else
+ return -1;
+}
+
+
+int FreeCyaSSL(void)
+{
+ if (FreeMutex(&mutex) == 0)
+ return 0;
+ else
+ return -1;
+}
+
+
+#ifndef NO_SESSION_CACHE
+
+
+static INLINE word32 HashSession(const byte* sessionID)
+{
+ /* id is random, just make 32 bit number from first 4 bytes for now */
+ return (sessionID[0] << 24) | (sessionID[1] << 16) | (sessionID[2] << 8) |
+ sessionID[3];
+}
+
+
+void SSL_flush_sessions(SSL_CTX* ctx, long tm)
+{
+ /* static table now, no flusing needed */
+}
+
+
+SSL_SESSION* GetSession(SSL* ssl, byte* masterSecret)
+{
+ SSL_SESSION* ret = 0;
+ const byte* id = ssl->arrays.sessionID;
+ word32 row;
+ int idx;
+
+ if (ssl->options.sessionCacheOff)
+ return 0;
+
+ row = HashSession(id) % SESSION_ROWS;
+
+ if (LockMutex(&mutex) != 0)
+ return 0;
+
+ if (SessionCache[row].totalCount >= SESSIONS_PER_ROW)
+ idx = SESSIONS_PER_ROW - 1;
+ else
+ idx = SessionCache[row].nextIdx - 1;
+
+ for (; idx >= 0; idx--) {
+ SSL_SESSION* current;
+
+ if (idx >= SESSIONS_PER_ROW) /* server could have restarted, idx */
+ break; /* would be word32(-1) and seg fault */
+
+ current = &SessionCache[row].Sessions[idx];
+ if (XMEMCMP(current->sessionID, id, ID_LEN) == 0) {
+ if (LowResTimer() < (current->bornOn + current->timeout)) {
+ ret = current;
+ if (masterSecret)
+ XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN);
+ }
+ break;
+ }
+ }
+
+ UnLockMutex(&mutex);
+
+ return ret;
+}
+
+
+int SetSession(SSL* ssl, SSL_SESSION* session)
+{
+ if (ssl->options.sessionCacheOff)
+ return SSL_FAILURE;
+
+ if (LowResTimer() < (session->bornOn + session->timeout)) {
+ ssl->session = *session;
+ ssl->options.resuming = 1;
+
+#ifdef SESSION_CERTS
+ ssl->version = session->version;
+ ssl->options.cipherSuite = session->cipherSuite;
+#endif
+
+ return SSL_SUCCESS;
+ }
+ return SSL_FAILURE; /* session timed out */
+}
+
+
+int AddSession(SSL* ssl)
+{
+ word32 row, idx;
+
+ if (ssl->options.sessionCacheOff)
+ return 0;
+
+ row = HashSession(ssl->arrays.sessionID) % SESSION_ROWS;
+
+ if (LockMutex(&mutex) != 0)
+ return -1;
+
+ idx = SessionCache[row].nextIdx++;
+
+ XMEMCPY(SessionCache[row].Sessions[idx].masterSecret,
+ ssl->arrays.masterSecret, SECRET_LEN);
+ XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays.sessionID,
+ ID_LEN);
+
+ SessionCache[row].Sessions[idx].timeout = DEFAULT_TIMEOUT;
+ SessionCache[row].Sessions[idx].bornOn = LowResTimer();
+
+#ifdef SESSION_CERTS
+ SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count;
+ XMEMCPY(SessionCache[row].Sessions[idx].chain.certs,
+ ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH);
+
+ SessionCache[row].Sessions[idx].version = ssl->version;
+ SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite;
+#endif
+
+ SessionCache[row].totalCount++;
+ if (SessionCache[row].nextIdx == SESSIONS_PER_ROW)
+ SessionCache[row].nextIdx = 0;
+
+ if (UnLockMutex(&mutex) != 0)
+ return -1;
+
+ return 0;
+}
+
+
+ #ifdef SESSION_STATS
+
+ void PrintSessionStats(void)
+ {
+ word32 totalSessionsSeen = 0;
+ word32 totalSessionsNow = 0;
+ word32 rowNow;
+ int i;
+ double E; /* expected freq */
+ double chiSquare = 0;
+
+ for (i = 0; i < SESSION_ROWS; i++) {
+ totalSessionsSeen += SessionCache[i].totalCount;
+
+ if (SessionCache[i].totalCount >= SESSIONS_PER_ROW)
+ rowNow = SESSIONS_PER_ROW;
+ else if (SessionCache[i].nextIdx == 0)
+ rowNow = 0;
+ else
+ rowNow = SessionCache[i].nextIdx;
+
+ totalSessionsNow += rowNow;
+ }
+
+ printf("Total Sessions Seen = %d\n", totalSessionsSeen);
+ printf("Total Sessions Now = %d\n", totalSessionsNow);
+
+ E = (double)totalSessionsSeen / SESSION_ROWS;
+
+ for (i = 0; i < SESSION_ROWS; i++) {
+ double diff = SessionCache[i].totalCount - E;
+ diff *= diff; /* sqaure */
+ diff /= E; /* normalize */
+
+ chiSquare += diff;
+ }
+ printf(" chi-square = %5.1f, d.f. = %d\n", chiSquare,
+ SESSION_ROWS - 1);
+ if (SESSION_ROWS == 11)
+ printf(" .05 p value = 18.3, chi-square should be less\n");
+ else if (SESSION_ROWS == 211)
+ printf(".05 p value = 244.8, chi-square should be less\n");
+ else if (SESSION_ROWS == 5981)
+ printf(".05 p value = 6161.0, chi-square should be less\n");
+ printf("\n");
+ }
+
+ #endif /* SESSION_STATS */
+
+#endif /* NO_SESSION_CACHE */
+
+
+/* call before SSL_connect, if verifying will add name check to
+ date check and signature check */
+int CyaSSL_check_domain_name(SSL* ssl, const char* dn)
+{
+ if (ssl->buffers.domainName.buffer)
+ XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+ ssl->buffers.domainName.length = (word32)XSTRLEN(dn) + 1;
+ ssl->buffers.domainName.buffer = (byte*) XMALLOC(
+ ssl->buffers.domainName.length, ssl->heap, DYNAMIC_TYPE_DOMAIN);
+
+ if (ssl->buffers.domainName.buffer) {
+ XSTRNCPY((char*)ssl->buffers.domainName.buffer, dn,
+ ssl->buffers.domainName.length);
+ return SSL_SUCCESS;
+ }
+ else {
+ ssl->error = MEMORY_ERROR;
+ return SSL_FAILURE;
+ }
+}
+
+
+/* turn on CyaSSL zlib compression
+ returns 0 for success, else error (not built in)
+*/
+int CyaSSL_set_compression(SSL* ssl)
+{
+#ifdef HAVE_LIBZ
+ ssl->options.usingCompression = 1;
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+
+#ifndef USE_WINDOWS_API
+ #ifndef NO_WRITEV
+
+ /* simulate writev semantics, doesn't actually do block at a time though
+ because of SSL_write behavior and because front adds may be small */
+ int CyaSSL_writev(SSL* ssl, const struct iovec* iov, int iovcnt)
+ {
+ byte tmp[OUTPUT_RECORD_SIZE];
+ byte* buffer = tmp;
+ int send = 0;
+ int newBuffer = 0;
+ int idx = 0;
+ int i;
+ int ret;
+
+ for (i = 0; i < iovcnt; i++)
+ send += iov[i].iov_len;
+
+ if (send > sizeof(tmp)) {
+ byte* tmp2 = (byte*) XMALLOC(send, ssl->heap,
+ DYNAMIC_TYPE_WRITEV);
+ if (!tmp2)
+ return MEMORY_ERROR;
+ buffer = tmp2;
+ newBuffer = 1;
+ }
+
+ for (i = 0; i < iovcnt; i++) {
+ XMEMCPY(&buffer[idx], iov[i].iov_base, iov[i].iov_len);
+ idx += iov[i].iov_len;
+ }
+
+ ret = SSL_write(ssl, buffer, send);
+
+ if (newBuffer) XFREE(buffer, ssl->heap, DYNAMIC_TYPE_WRITEV);
+
+ return ret;
+ }
+ #endif
+#endif
+
+
+#ifdef CYASSL_CALLBACKS
+
+ typedef struct itimerval Itimerval;
+
+ /* don't keep calling simple functions while setting up timer and singals
+ if no inlining these are the next best */
+
+ #define AddTimes(a, b, c) \
+ do { \
+ c.tv_sec = a.tv_sec + b.tv_sec; \
+ c.tv_usec = a.tv_usec + b.tv_usec; \
+ if (c.tv_sec >= 1000000) { \
+ c.tv_sec++; \
+ c.tv_usec -= 1000000; \
+ } \
+ } while (0)
+
+
+ #define SubtractTimes(a, b, c) \
+ do { \
+ c.tv_sec = a.tv_sec - b.tv_sec; \
+ c.tv_usec = a.tv_usec - b.tv_usec; \
+ if (c.tv_sec < 0) { \
+ c.tv_sec--; \
+ c.tv_usec += 1000000; \
+ } \
+ } while (0)
+
+ #define CmpTimes(a, b, cmp) \
+ ((a.tv_sec == b.tv_sec) ? \
+ (a.tv_usec cmp b.tv_usec) : \
+ (a.tv_sec cmp b.tv_sec)) \
+
+
+ /* do nothing handler */
+ static void myHandler(int signo)
+ {
+ return;
+ }
+
+
+ static int CyaSSL_ex_wrapper(SSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb, Timeval timeout)
+ {
+ int ret = -1;
+ int oldTimerOn = 0; /* was timer already on */
+ Timeval startTime;
+ Timeval endTime;
+ Timeval totalTime;
+ Itimerval myTimeout;
+ Itimerval oldTimeout; /* if old timer adjust from total time to reset */
+ struct sigaction act, oact;
+
+ #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; }
+
+ if (hsCb) {
+ ssl->hsInfoOn = 1;
+ InitHandShakeInfo(&ssl->handShakeInfo);
+ }
+ if (toCb) {
+ ssl->toInfoOn = 1;
+ InitTimeoutInfo(&ssl->timeoutInfo);
+
+ if (gettimeofday(&startTime, 0) < 0)
+ ERR_OUT(GETTIME_ERROR);
+
+ /* use setitimer to simulate getitimer, init 0 myTimeout */
+ myTimeout.it_interval.tv_sec = 0;
+ myTimeout.it_interval.tv_usec = 0;
+ myTimeout.it_value.tv_sec = 0;
+ myTimeout.it_value.tv_usec = 0;
+ if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0)
+ ERR_OUT(SETITIMER_ERROR);
+
+ if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) {
+ oldTimerOn = 1;
+
+ /* is old timer going to expire before ours */
+ if (CmpTimes(oldTimeout.it_value, timeout, <)) {
+ timeout.tv_sec = oldTimeout.it_value.tv_sec;
+ timeout.tv_usec = oldTimeout.it_value.tv_usec;
+ }
+ }
+ myTimeout.it_value.tv_sec = timeout.tv_sec;
+ myTimeout.it_value.tv_usec = timeout.tv_usec;
+
+ /* set up signal handler, don't restart socket send/recv */
+ act.sa_handler = myHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+#ifdef SA_INTERRUPT
+ act.sa_flags |= SA_INTERRUPT;
+#endif
+ if (sigaction(SIGALRM, &act, &oact) < 0)
+ ERR_OUT(SIGACT_ERROR);
+
+ if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0)
+ ERR_OUT(SETITIMER_ERROR);
+ }
+
+ /* do main work */
+#ifndef NO_CYASSL_CLIENT
+ if (ssl->options.side == CLIENT_END)
+ ret = SSL_connect(ssl);
+#endif
+#ifndef NO_CYASSL_SERVER
+ if (ssl->options.side == SERVER_END)
+ ret = SSL_accept(ssl);
+#endif
+
+ /* do callbacks */
+ if (toCb) {
+ if (oldTimerOn) {
+ gettimeofday(&endTime, 0);
+ SubtractTimes(endTime, startTime, totalTime);
+ /* adjust old timer for elapsed time */
+ if (CmpTimes(totalTime, oldTimeout.it_value, <))
+ SubtractTimes(oldTimeout.it_value, totalTime,
+ oldTimeout.it_value);
+ else {
+ /* reset value to interval, may be off */
+ oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec;
+ oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec;
+ }
+ /* keep iter the same whether there or not */
+ }
+ /* restore old handler */
+ if (sigaction(SIGALRM, &oact, 0) < 0)
+ ret = SIGACT_ERROR; /* more pressing error, stomp */
+ else
+ /* use old settings which may turn off (expired or not there) */
+ if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0)
+ ret = SETITIMER_ERROR;
+
+ /* if we had a timeout call callback */
+ if (ssl->timeoutInfo.timeoutName[0]) {
+ ssl->timeoutInfo.timeoutValue.tv_sec = timeout.tv_sec;
+ ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec;
+ (toCb)(&ssl->timeoutInfo);
+ }
+ /* clean up */
+ FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap);
+ ssl->toInfoOn = 0;
+ }
+ if (hsCb) {
+ FinishHandShakeInfo(&ssl->handShakeInfo, ssl);
+ (hsCb)(&ssl->handShakeInfo);
+ ssl->hsInfoOn = 0;
+ }
+ return ret;
+ }
+
+
+#ifndef NO_CYASSL_CLIENT
+
+ int CyaSSL_connect_ex(SSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb, Timeval timeout)
+ {
+ return CyaSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+ }
+
+#endif
+
+
+#ifndef NO_CYASSL_SERVER
+
+ int CyaSSL_accept_ex(SSL* ssl, HandShakeCallBack hsCb,
+ TimeoutCallBack toCb,Timeval timeout)
+ {
+ return CyaSSL_ex_wrapper(ssl, hsCb, toCb, timeout);
+ }
+
+#endif
+
+#endif /* CYASSL_CALLBACKS */
+
+
+#ifndef NO_PSK
+
+ void SSL_CTX_set_psk_client_callback(SSL_CTX* ctx, psk_client_callback cb)
+ {
+ ctx->havePSK = 1;
+ ctx->client_psk_cb = cb;
+ }
+
+
+ void SSL_set_psk_client_callback(SSL* ssl, psk_client_callback cb)
+ {
+ ssl->options.havePSK = 1;
+ ssl->options.client_psk_cb = cb;
+
+ InitSuites(&ssl->suites, ssl->version,TRUE,TRUE, ssl->options.haveNTRU);
+ }
+
+
+ void SSL_CTX_set_psk_server_callback(SSL_CTX* ctx, psk_server_callback cb)
+ {
+ ctx->havePSK = 1;
+ ctx->server_psk_cb = cb;
+ }
+
+
+ void SSL_set_psk_server_callback(SSL* ssl, psk_server_callback cb)
+ {
+ ssl->options.havePSK = 1;
+ ssl->options.server_psk_cb = cb;
+
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, TRUE,
+ ssl->options.haveNTRU);
+ }
+
+
+ const char* SSL_get_psk_identity_hint(const SSL* ssl)
+ {
+ return ssl->arrays.server_hint;
+ }
+
+
+ const char* SSL_get_psk_identity(const SSL* ssl)
+ {
+ return ssl->arrays.client_identity;
+ }
+
+
+ int SSL_CTX_use_psk_identity_hint(SSL_CTX* ctx, const char* hint)
+ {
+ if (hint == 0)
+ ctx->server_hint[0] = 0;
+ else
+ XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN);
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_use_psk_identity_hint(SSL* ssl, const char* hint)
+ {
+ if (hint == 0)
+ ssl->arrays.server_hint[0] = 0;
+ else
+ XSTRNCPY(ssl->arrays.server_hint, hint, MAX_PSK_ID_LEN);
+ return SSL_SUCCESS;
+ }
+
+#endif /* NO_PSK */
+
+
+#if defined(NO_FILESYSTEM) || defined(MICRIUM)
+
+ /* CyaSSL extension allows DER files to be loaded from buffers as well */
+ int CyaSSL_CTX_load_verify_buffer(SSL_CTX* ctx, const unsigned char* buffer,
+ long sz, int format)
+ {
+ return ProcessBuffer(ctx, buffer, sz, format, CA_TYPE);
+ }
+
+
+ int CyaSSL_CTX_use_certificate_buffer(SSL_CTX* ctx,
+ const unsigned char* buffer,long sz,int format)
+ {
+ return ProcessBuffer(ctx, buffer, sz, format, CERT_TYPE);
+ }
+
+
+ int CyaSSL_CTX_use_PrivateKey_buffer(SSL_CTX* ctx,
+ const unsigned char* buffer,long sz,int format)
+ {
+ return ProcessBuffer(ctx, buffer, sz, format, PRIVATEKEY_TYPE);
+ }
+
+
+ int CyaSSL_CTX_use_certificate_chain_buffer(SSL_CTX* ctx,
+ const unsigned char* buffer, long sz)
+ {
+ /* add first to ctx, all tested implementations support this */
+ return ProcessBuffer(ctx, buffer, sz, SSL_FILETYPE_PEM, CA_TYPE);
+ }
+
+#endif /* NO_FILESYSTEM || MICRIUM */
+
+
+#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
+
+
+ int SSLeay_add_ssl_algorithms(void)
+ {
+ OpenSSL_add_all_algorithms();
+ return SSL_SUCCESS;
+ }
+
+
+ long SSL_CTX_sess_set_cache_size(SSL_CTX* ctx, long sz)
+ {
+ /* cache size fixed at compile time in CyaSSL */
+ return 0;
+ }
+
+
+ void SSL_CTX_set_quiet_shutdown(SSL_CTX* ctx, int mode)
+ {
+ if (mode)
+ ctx->quietShutdown = 1;
+ }
+
+
+ int SSL_CTX_check_private_key(SSL_CTX* ctx)
+ {
+ /* TODO: check private against public for RSA match */
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_set_bio(SSL* ssl, BIO* rd, BIO* wr)
+ {
+ SSL_set_rfd(ssl, rd->fd);
+ SSL_set_wfd(ssl, wr->fd);
+
+ ssl->biord = rd;
+ ssl->biowr = wr;
+ }
+
+
+ void SSL_CTX_set_client_CA_list(SSL_CTX* ctx, STACK_OF(X509_NAME)* names)
+ {
+
+ }
+
+
+ STACK_OF(X509_NAME)* SSL_load_client_CA_file(const char* fname)
+ {
+ return 0;
+ }
+
+
+ int SSL_CTX_set_default_verify_paths(SSL_CTX* ctx)
+ {
+ /* TODO:, not needed in goahead */
+ return SSL_NOT_IMPLEMENTED;
+ }
+
+
+ void SSL_set_accept_state(SSL* ssl)
+ {
+ byte havePSK = 0;
+
+ ssl->options.side = SERVER_END;
+ /* reset suites in case user switched */
+#ifndef NO_PSK
+ havePSK = ssl->options.havePSK;
+#endif
+ InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK,
+ ssl->options.haveNTRU);
+ }
+
+
+ void OpenSSL_add_all_algorithms(void)
+ {
+ InitCyaSSL();
+ }
+
+
+ int SSLeay_add_all_algorithms(void)
+ {
+ OpenSSL_add_all_algorithms();
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_CTX_set_tmp_rsa_callback(SSL_CTX* ctx, RSA*(*f)(SSL*, int, int))
+ {
+ /* CyaSSL verifies all these internally */
+ }
+
+
+ void SSL_set_shutdown(SSL* ssl, int opt)
+ {
+
+ }
+
+
+ long SSL_CTX_set_options(SSL_CTX* ctx, long opt)
+ {
+ /* goahead calls with 0, do nothing */
+ return opt;
+ }
+
+
+ int SSL_set_rfd(SSL* ssl, int rfd)
+ {
+ ssl->rfd = rfd; /* not used directly to allow IO callbacks */
+
+ ssl->IOCB_ReadCtx = &ssl->rfd;
+
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_set_wfd(SSL* ssl, int wfd)
+ {
+ ssl->wfd = wfd; /* not used directly to allow IO callbacks */
+
+ ssl->IOCB_WriteCtx = &ssl->wfd;
+
+ return SSL_SUCCESS;
+ }
+
+
+ RSA* RSA_generate_key(int len, unsigned long bits, void(*f)(int,
+ int, void*), void* data)
+ {
+ /* no tmp key needed, actual generation not supported */
+ return 0;
+ }
+
+
+ X509_NAME* X509_get_issuer_name(X509* cert)
+ {
+ return &cert->issuer;
+ }
+
+
+ X509_NAME* X509_get_subject_name(X509* cert)
+ {
+ return &cert->subject;
+ }
+
+
+ /* copy name into buffer, at most sz bytes, if buffer is null will
+ malloc buffer, call responsible for freeing */
+ char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz)
+ {
+ int copySz = min(sz, name->sz);
+ if (!name->sz) return buffer;
+
+ if (!buffer) {
+ buffer = (char*)XMALLOC(name->sz, 0, DYNAMIC_TYPE_OPENSSL);
+ if (!buffer) return buffer;
+ copySz = name->sz;
+ }
+
+ if (copySz == 0)
+ return buffer;
+
+ XMEMCPY(buffer, name->name, copySz - 1);
+ buffer[copySz - 1] = 0;
+
+ return buffer;
+ }
+
+
+ X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ BIO_METHOD* BIO_f_buffer(void)
+ {
+ static BIO_METHOD meth;
+ meth.type = BIO_BUFFER;
+
+ return &meth;
+ }
+
+
+ long BIO_set_write_buffer_size(BIO* bio, long size)
+ {
+ /* CyaSSL has internal buffer, compatibility only */
+ return size;
+ }
+
+
+ BIO_METHOD* BIO_f_ssl(void)
+ {
+ static BIO_METHOD meth;
+ meth.type = BIO_SSL;
+
+ return &meth;
+ }
+
+
+ BIO* BIO_new_socket(int sfd, int close)
+ {
+ BIO* bio = (BIO*) XMALLOC(sizeof(BIO), 0, DYNAMIC_TYPE_OPENSSL);
+ if (bio) {
+ bio->type = BIO_SOCKET;
+ bio->close = close;
+ bio->eof = 0;
+ bio->ssl = 0;
+ bio->fd = sfd;
+ bio->prev = 0;
+ bio->next = 0;
+ }
+ return bio;
+ }
+
+
+ int BIO_eof(BIO* b)
+ {
+ if (b->eof)
+ return 1;
+
+ return 0;
+ }
+
+
+ long BIO_set_ssl(BIO* b, SSL* ssl, int close)
+ {
+ b->ssl = ssl;
+ b->close = close;
+ /* add to ssl for bio free if SSL_free called before/instead of free_all? */
+
+ return 0;
+ }
+
+
+ BIO* BIO_new(BIO_METHOD* method)
+ {
+ BIO* bio = (BIO*) XMALLOC(sizeof(BIO), 0, DYNAMIC_TYPE_OPENSSL);
+ if (bio) {
+ bio->type = method->type;
+ bio->close = 0;
+ bio->eof = 0;
+ bio->ssl = 0;
+ bio->fd = 0;
+ bio->prev = 0;
+ bio->next = 0;
+ }
+ return bio;
+ }
+
+
+#ifdef USE_WINDOWS_API
+ #define CloseSocket(s) closesocket(s)
+#else
+ #define CloseSocket(s) close(s)
+#endif
+
+ int BIO_free(BIO* bio)
+ {
+ /* unchain?, doesn't matter in goahead since from free all */
+ if (bio) {
+ if (bio->close) {
+ if (bio->ssl)
+ SSL_free(bio->ssl);
+ if (bio->fd)
+ CloseSocket(bio->fd);
+ }
+ XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
+ }
+ return 0;
+ }
+
+
+ int BIO_free_all(BIO* bio)
+ {
+ BIO* next = bio;
+
+ while ( (bio = next) ) {
+ next = bio->next;
+ BIO_free(bio);
+ }
+ return 0;
+ }
+
+
+ int BIO_read(BIO* bio, void* buf, int len)
+ {
+ int ret;
+ SSL* ssl = 0;
+ BIO* front = bio;
+
+ /* already got eof, again is error */
+ if (front->eof)
+ return -1;
+
+ while(bio && ((ssl = bio->ssl) == 0) )
+ bio = bio->next;
+
+ if (ssl == 0) return -1;
+
+ ret = SSL_read(ssl, buf, len);
+ if (ret == 0)
+ front->eof = 1;
+ else if (ret < 0) {
+ int err = SSL_get_error(ssl, 0);
+ if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) )
+ front->eof = 1;
+ }
+ return ret;
+ }
+
+
+ int BIO_write(BIO* bio, const void* data, int len)
+ {
+ int ret;
+ SSL* ssl = 0;
+ BIO* front = bio;
+
+ /* already got eof, again is error */
+ if (front->eof)
+ return -1;
+
+ while(bio && ((ssl = bio->ssl) == 0) )
+ bio = bio->next;
+
+ if (ssl == 0) return -1;
+
+ ret = SSL_write(ssl, data, len);
+ if (ret == 0)
+ front->eof = 1;
+ else if (ret < 0) {
+ int err = SSL_get_error(ssl, 0);
+ if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) )
+ front->eof = 1;
+ }
+
+ return ret;
+ }
+
+
+ BIO* BIO_push(BIO* top, BIO* append)
+ {
+ top->next = append;
+ append->prev = top;
+
+ return top;
+ }
+
+
+ int BIO_flush(BIO* bio)
+ {
+ /* for CyaSSL no flushing needed */
+ return 1;
+ }
+
+
+#endif /* OPENSSL_EXTRA || GOAHEAD_WS */
+
+
+#ifdef OPENSSL_EXTRA
+
+ unsigned long SSLeay(void)
+ {
+ return SSLEAY_VERSION_NUMBER;
+ }
+
+
+ const char* SSLeay_version(int type)
+ {
+ static const char* version = "SSLeay CyaSSL compatibility";
+ return version;
+ }
+
+
+ void MD5_Init(MD5_CTX* md5)
+ {
+ typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1];
+ (void)sizeof(md5_test);
+
+ InitMd5((Md5*)md5);
+ }
+
+
+ void MD5_Update(MD5_CTX* md5, const void* input, unsigned long sz)
+ {
+ Md5Update((Md5*)md5, (const byte*)input, sz);
+ }
+
+
+ void MD5_Final(byte* input, MD5_CTX* md5)
+ {
+ Md5Final((Md5*)md5, input);
+ }
+
+
+ void SHA_Init(SHA_CTX* sha)
+ {
+ typedef char sha_test[sizeof(SHA_CTX) >= sizeof(Sha) ? 1 : -1];
+ (void)sizeof(sha_test);
+
+ InitSha((Sha*)sha);
+ }
+
+
+ void SHA_Update(SHA_CTX* sha, const void* input, unsigned long sz)
+ {
+ ShaUpdate((Sha*)sha, (const byte*)input, sz);
+ }
+
+
+ void SHA_Final(byte* input, SHA_CTX* sha)
+ {
+ ShaFinal((Sha*)sha, input);
+ }
+
+
+ const EVP_MD* EVP_md5(void)
+ {
+ static const char* type = "MD5";
+ return type;
+ }
+
+
+ const EVP_MD* EVP_sha1(void)
+ {
+ static const char* type = "SHA";
+ return type;
+ }
+
+
+ void EVP_MD_CTX_init(EVP_MD_CTX* ctx)
+ {
+ /* do nothing */
+ }
+
+
+ int EVP_MD_CTX_cleanup(EVP_MD_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ int EVP_DigestInit(EVP_MD_CTX* ctx, const EVP_MD* type)
+ {
+ if (XSTRNCMP(type, "MD5", 3) == 0) {
+ ctx->macType = MD5;
+ MD5_Init((MD5_CTX*)&ctx->hash);
+ }
+ else if (XSTRNCMP(type, "SHA", 3) == 0) {
+ ctx->macType = SHA;
+ SHA_Init((SHA_CTX*)&ctx->hash);
+ }
+ else
+ return -1;
+
+ return 0;
+ }
+
+
+ int EVP_DigestUpdate(EVP_MD_CTX* ctx, const void* data, size_t sz)
+ {
+ if (ctx->macType == MD5)
+ MD5_Update((MD5_CTX*)&ctx->hash, data, (unsigned long)sz);
+ else if (ctx->macType == SHA)
+ SHA_Update((SHA_CTX*)&ctx->hash, data, (unsigned long)sz);
+ else
+ return -1;
+
+ return 0;
+ }
+
+
+ int EVP_DigestFinal(EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s)
+ {
+ if (ctx->macType == MD5) {
+ MD5_Final(md, (MD5_CTX*)&ctx->hash);
+ if (s) *s = MD5_DIGEST_SIZE;
+ }
+ else if (ctx->macType == SHA) {
+ SHA_Final(md, (SHA_CTX*)&ctx->hash);
+ if (s) *s = SHA_DIGEST_SIZE;
+ }
+ else
+ return -1;
+
+ return 0;
+ }
+
+
+ int EVP_DigestFinal_ex(EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s)
+ {
+ return EVP_DigestFinal(ctx, md, s);
+ }
+
+
+ unsigned char* HMAC(const EVP_MD* evp_md, const void* key, int key_len,
+ const unsigned char* d, int n, unsigned char* md, unsigned int* md_len)
+ {
+ Hmac hmac;
+
+ if (!md) return 0; /* no static buffer support */
+
+ if (XSTRNCMP(evp_md, "MD5", 3) == 0) {
+ HmacSetKey(&hmac, MD5, key, key_len);
+ if (md_len) *md_len = MD5_DIGEST_SIZE;
+ }
+ else if (XSTRNCMP(evp_md, "SHA", 3) == 0) {
+ HmacSetKey(&hmac, SHA, key, key_len);
+ if (md_len) *md_len = SHA_DIGEST_SIZE;
+ }
+ else
+ return 0;
+
+ HmacUpdate(&hmac, d, n);
+ HmacFinal(&hmac, md);
+
+ return md;
+ }
+
+ unsigned long ERR_get_error(void)
+ {
+ /* TODO: */
+ return 0;
+ }
+
+ void ERR_clear_error(void)
+ {
+ /* TODO: */
+ }
+
+
+ int RAND_status(void)
+ {
+ return 1; /* CTaoCrypt provides enough seed internally */
+ }
+
+
+ int RAND_bytes(unsigned char* buf, int num)
+ {
+ RNG rng;
+
+ if (InitRng(&rng))
+ return 0;
+
+ RNG_GenerateBlock(&rng, buf, num);
+
+ return 1;
+ }
+
+
+ int DES_key_sched(const_DES_cblock* key, DES_key_schedule* schedule)
+ {
+ XMEMCPY(schedule, key, sizeof(const_DES_cblock));
+ return 0;
+ }
+
+
+ void DES_cbc_encrypt(const unsigned char* input, unsigned char* output,
+ long length, DES_key_schedule* schedule, DES_cblock* ivec,
+ int enc)
+ {
+ Des des;
+ Des_SetKey(&des, (const byte*)schedule, (const byte*)ivec, !enc);
+
+ if (enc)
+ Des_CbcEncrypt(&des, output, input, length);
+ else
+ Des_CbcDecrypt(&des, output, input, length);
+ }
+
+
+ /* correctly sets ivec for next call */
+ void DES_ncbc_encrypt(const unsigned char* input, unsigned char* output,
+ long length, DES_key_schedule* schedule, DES_cblock* ivec,
+ int enc)
+ {
+ Des des;
+ Des_SetKey(&des, (const byte*)schedule, (const byte*)ivec, !enc);
+
+ if (enc)
+ Des_CbcEncrypt(&des, output, input, length);
+ else
+ Des_CbcDecrypt(&des, output, input, length);
+
+ XMEMCPY(ivec, output + length - sizeof(DES_cblock), sizeof(DES_cblock));
+ }
+
+
+ void ERR_free_strings(void)
+ {
+ /* handled internally */
+ }
+
+
+ void ERR_remove_state(unsigned long state)
+ {
+ /* TODO: GetErrors().Remove(); */
+ }
+
+
+ void EVP_cleanup(void)
+ {
+ /* nothing to do here */
+ }
+
+
+ void CRYPTO_cleanup_all_ex_data(void)
+ {
+ /* nothing to do here */
+ }
+
+
+ long SSL_CTX_set_mode(SSL_CTX* ctx, long mode)
+ {
+ /* SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is CyaSSL default mode */
+
+ if (mode == SSL_MODE_ENABLE_PARTIAL_WRITE)
+ ctx->partialWrite = 1;
+
+ return mode;
+ }
+
+
+ long SSL_CTX_get_mode(SSL_CTX* ctx)
+ {
+ /* TODO: */
+ return 0;
+ }
+
+
+ void SSL_CTX_set_default_read_ahead(SSL_CTX* ctx, int m)
+ {
+ /* TODO: maybe? */
+ }
+
+
+ int SSL_CTX_set_session_id_context(SSL_CTX* ctx,
+ const unsigned char* sid_ctx,
+ unsigned int sid_ctx_len)
+ {
+ /* No application specific context needed for cyaSSL */
+ return SSL_SUCCESS;
+ }
+
+
+ long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx)
+ {
+ /* TODO: maybe? */
+ return (~0);
+ }
+
+ unsigned long ERR_get_error_line_data(const char** file, int* line,
+ const char** data, int *flags)
+ {
+ /* Not implemented */
+ return 0;
+ }
+
+
+ X509* SSL_get_peer_certificate(SSL* ssl)
+ {
+ if (ssl->peerCert.issuer.sz)
+ return &ssl->peerCert;
+ else
+ return 0;
+ }
+
+
+
+ int SSL_set_ex_data(SSL* ssl, int idx, void* data)
+ {
+ return 0;
+ }
+
+
+ int SSL_get_shutdown(const SSL* ssl)
+ {
+ return 0;
+ }
+
+
+ int SSL_set_session_id_context(SSL* ssl, const unsigned char* id,
+ unsigned int len)
+ {
+ return 0;
+ }
+
+
+ void SSL_set_connect_state(SSL* ssl)
+ {
+ /* client by default */
+ }
+
+
+ int SSL_session_reused(SSL* ssl)
+ {
+ return ssl->options.resuming;
+ }
+
+
+ void SSL_SESSION_free(SSL_SESSION* session)
+ {
+
+ }
+
+
+ const char* SSL_get_version(SSL* ssl)
+ {
+ if (ssl->version.major == 3) {
+ switch (ssl->version.minor) {
+ case 0 :
+ return "SSLv3";
+ case 1 :
+ return "TLSv1";
+ case 2 :
+ return "TLSv1.1";
+ case 3 :
+ return "TLSv1.2";
+ }
+ }
+ return "unknown";
+ }
+
+
+ SSL_CIPHER* SSL_get_current_cipher(SSL* ssl)
+ {
+ return &ssl->cipher;
+ }
+
+
+ const char* SSL_CIPHER_get_name(const SSL_CIPHER* cipher)
+ {
+ if (cipher) {
+ switch (cipher->ssl->options.cipherSuite) {
+ case SSL_RSA_WITH_RC4_128_SHA :
+ return "SSL_RSA_WITH_RC4_128_SHA";
+ case SSL_RSA_WITH_RC4_128_MD5 :
+ return "SSL_RSA_WITH_RC4_128_MD5";
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA :
+ return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
+ case TLS_RSA_WITH_AES_128_CBC_SHA :
+ return "TLS_RSA_WITH_AES_128_CBC_SHA";
+ case TLS_RSA_WITH_AES_256_CBC_SHA :
+ return "TLS_RSA_WITH_AES_256_CBC_SHA";
+ case TLS_PSK_WITH_AES_128_CBC_SHA :
+ return "TLS_PSK_WITH_AES_128_CBC_SHA";
+ case TLS_PSK_WITH_AES_256_CBC_SHA :
+ return "TLS_PSK_WITH_AES_256_CBC_SHA";
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA :
+ return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
+ return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+ case TLS_RSA_WITH_HC_128_CBC_MD5 :
+ return "TLS_RSA_WITH_HC_128_CBC_MD5";
+ case TLS_RSA_WITH_HC_128_CBC_SHA :
+ return "TLS_RSA_WITH_HC_128_CBC_SHA";
+ case TLS_RSA_WITH_RABBIT_CBC_SHA :
+ return "TLS_RSA_WITH_RABBIT_CBC_SHA";
+ case TLS_NTRU_RSA_WITH_RC4_128_SHA :
+ return "TLS_NTRU_RSA_WITH_RC4_128_SHA";
+ case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA :
+ return "TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA";
+ case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA :
+ return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA";
+ case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA :
+ return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA";
+ }
+ }
+
+ return "NONE";
+ }
+
+
+ char* SSL_CIPHER_description(SSL_CIPHER* cipher, char* buffer, int len)
+ {
+ return 0;
+ }
+
+
+ SSL_SESSION* SSL_get1_session(SSL* ssl) /* what's ref count */
+ {
+ return 0;
+ }
+
+
+ void X509_free(X509* buf)
+ {
+
+ }
+
+
+ void OPENSSL_free(void* buf)
+ {
+
+ }
+
+
+ int OCSP_parse_url(char* url, char** host, char** port, char** path,
+ int* ssl)
+ {
+ return 0;
+ }
+
+
+ SSL_METHOD* SSLv2_client_method(void)
+ {
+ return 0;
+ }
+
+
+ SSL_METHOD* SSLv2_server_method(void)
+ {
+ return 0;
+ }
+
+
+#ifndef NO_MD4
+
+ void MD4_Init(MD4_CTX* md4)
+ {
+ /* make sure we have a big enough buffer */
+ typedef char ok[sizeof(md4->buffer) >= sizeof(Md4) ? 1 : -1];
+ (void) sizeof(ok);
+
+ InitMd4((Md4*)md4);
+ }
+
+
+ void MD4_Update(MD4_CTX* md4, const void* data, size_t len)
+ {
+ Md4Update((Md4*)md4, (const byte*)data, (word32)len);
+ }
+
+
+ void MD4_Final(unsigned char* digest, MD4_CTX* md4)
+ {
+ Md4Final((Md4*)md4, digest);
+ }
+
+#endif /* NO_MD4 */
+
+
+ BIO* BIO_pop(BIO* top)
+ {
+ return 0;
+ }
+
+
+ int BIO_pending(BIO* bio)
+ {
+ return 0;
+ }
+
+
+
+ BIO_METHOD* BIO_s_mem(void)
+ {
+ return 0;
+ }
+
+
+ BIO_METHOD* BIO_f_base64(void)
+ {
+ return 0;
+ }
+
+
+ void BIO_set_flags(BIO* bio, int flags)
+ {
+
+ }
+
+
+
+ void RAND_screen(void)
+ {
+
+ }
+
+
+ const char* RAND_file_name(char* fname, size_t len)
+ {
+ return 0;
+ }
+
+
+ int RAND_write_file(const char* fname)
+ {
+ return 0;
+ }
+
+
+ int RAND_load_file(const char* fname, long len)
+ {
+ /* CTaoCrypt provides enough entropy internally or will report error */
+ if (len == -1)
+ return 1024;
+ else
+ return (int)len;
+ }
+
+
+ int RAND_egd(const char* path)
+ {
+ return 0;
+ }
+
+
+
+ COMP_METHOD* COMP_zlib(void)
+ {
+ return 0;
+ }
+
+
+ COMP_METHOD* COMP_rle(void)
+ {
+ return 0;
+ }
+
+
+ int SSL_COMP_add_compression_method(int method, void* data)
+ {
+ return 0;
+ }
+
+
+
+ int SSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2,
+ void* cb3)
+ {
+ return 0;
+ }
+
+
+ int CRYPTO_num_locks(void)
+ {
+ return 0;
+ }
+
+
+ void CRYPTO_set_id_callback(unsigned long (*f)(void))
+ {
+
+ }
+
+
+ void CRYPTO_set_locking_callback(void (*f)(int, int, const char*, int))
+ {
+
+ }
+
+
+ void CRYPTO_set_dynlock_create_callback(CRYPTO_dynlock_value* (*f)(
+ const char*, int))
+ {
+
+ }
+
+
+ void CRYPTO_set_dynlock_lock_callback(void (*f)(int, CRYPTO_dynlock_value*,
+ const char*, int))
+ {
+
+ }
+
+
+ void CRYPTO_set_dynlock_destroy_callback(void (*f)(CRYPTO_dynlock_value*,
+ const char*, int))
+ {
+
+ }
+
+
+
+ const char* X509_verify_cert_error_string(long err)
+ {
+ return 0;
+ }
+
+
+
+ int X509_LOOKUP_add_dir(X509_LOOKUP* lookup, const char* dir, long len)
+ {
+ return 0;
+ }
+
+
+ int X509_LOOKUP_load_file(X509_LOOKUP* lookup, const char* file, long len)
+ {
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void)
+ {
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_file(void)
+ {
+ return 0;
+ }
+
+
+
+ X509_LOOKUP* X509_STORE_add_lookup(X509_STORE* store, X509_LOOKUP_METHOD* m)
+ {
+ return 0;
+ }
+
+
+ X509_STORE* X509_STORE_new(void)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_get_by_subject(X509_STORE_CTX* ctx, int idx, X509_NAME* name,
+ X509_OBJECT* obj)
+ {
+ return 0;
+ }
+
+
+ int X509_STORE_CTX_init(X509_STORE_CTX* ctx, X509_STORE* store, X509* x509,
+ STACK_OF(X509)* sk)
+ {
+ return 0;
+ }
+
+
+ void X509_STORE_CTX_cleanup(X509_STORE_CTX* ctx)
+ {
+
+ }
+
+
+
+ ASN1_TIME* X509_CRL_get_lastUpdate(X509_CRL* crl)
+ {
+ return 0;
+ }
+
+
+ ASN1_TIME* X509_CRL_get_nextUpdate(X509_CRL* crl)
+ {
+ return 0;
+ }
+
+
+
+ EVP_PKEY* X509_get_pubkey(X509* x509)
+ {
+ return 0;
+ }
+
+
+ int X509_CRL_verify(X509_CRL* crl, EVP_PKEY* key)
+ {
+ return 0;
+ }
+
+
+ void X509_STORE_CTX_set_error(X509_STORE_CTX* ctx, int err)
+ {
+
+ }
+
+
+ void X509_OBJECT_free_contents(X509_OBJECT* obj)
+ {
+
+ }
+
+
+ void EVP_PKEY_free(EVP_PKEY* key)
+ {
+
+ }
+
+
+ int X509_cmp_current_time(const ASN1_TIME* time)
+ {
+ return 0;
+ }
+
+
+ int sk_X509_REVOKED_num(X509_REVOKED* revoked)
+ {
+ return 0;
+ }
+
+
+
+ X509_REVOKED* X509_CRL_get_REVOKED(X509_CRL* crl)
+ {
+ return 0;
+ }
+
+
+ X509_REVOKED* sk_X509_REVOKED_value(X509_REVOKED* revoked, int value)
+ {
+ return 0;
+ }
+
+
+
+ ASN1_INTEGER* X509_get_serialNumber(X509* x509)
+ {
+ return 0;
+ }
+
+
+
+ int ASN1_TIME_print(BIO* bio, const ASN1_TIME* time)
+ {
+ return 0;
+ }
+
+
+
+ int ASN1_INTEGER_cmp(const ASN1_INTEGER* a, const ASN1_INTEGER* b)
+ {
+ return 0;
+ }
+
+
+ long ASN1_INTEGER_get(const ASN1_INTEGER* i)
+ {
+ return 0;
+ }
+
+
+
+ void* X509_STORE_CTX_get_ex_data(X509_STORE_CTX* ctx, int idx)
+ {
+ return 0;
+ }
+
+
+ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
+ {
+ return 0;
+ }
+
+
+ void* SSL_get_ex_data(const SSL* ssl, int idx)
+ {
+ return 0;
+ }
+
+
+ void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX* ctx, void* userdata)
+ {
+ ctx->userdata = userdata;
+ }
+
+
+ void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb)
+ {
+ ctx->passwd_cb = cb;
+ }
+
+
+ long SSL_CTX_set_timeout(SSL_CTX* ctx, long to)
+ {
+ return 0;
+ }
+
+
+ void SSL_CTX_set_info_callback(SSL_CTX* ctx, void (*f)())
+ {
+
+ }
+
+
+ unsigned long ERR_peek_error(void)
+ {
+ return 0;
+ }
+
+
+ int ERR_GET_REASON(int err)
+ {
+ return 0;
+ }
+
+
+ char* SSL_alert_type_string_long(int alert)
+ {
+ return 0;
+ }
+
+
+ char* SSL_alert_desc_string_long(int alert)
+ {
+ return 0;
+ }
+
+
+ char* SSL_state_string_long(SSL* ssl)
+ {
+ return 0;
+ }
+
+
+
+ void RSA_free(RSA* rsa)
+ {
+
+ }
+
+
+ int PEM_def_callback(char* name, int num, int w, void* key)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_accept(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_connect(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_accept_good(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_connect_good(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_hits(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_cb_hits(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_cache_full(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_misses(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_timeouts(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ long SSL_CTX_sess_number(SSL_CTX* ctx)
+ {
+ return 0;
+ }
+
+
+ void DES_set_key_unchecked(const_DES_cblock* des, DES_key_schedule* key)
+ {
+ }
+
+
+ void DES_set_odd_parity(DES_cblock* des)
+ {
+ }
+
+
+ void DES_ecb_encrypt(DES_cblock* desa, DES_cblock* desb,
+ DES_key_schedule* key, int len)
+ {
+ }
+
+ int BIO_printf(BIO* bio, const char* format, ...)
+ {
+ return 0;
+ }
+
+
+ int ASN1_UTCTIME_print(BIO* bio, const ASN1_UTCTIME* a)
+ {
+ return 0;
+ }
+
+
+ int sk_num(X509_REVOKED* rev)
+ {
+ return 0;
+ }
+
+
+ void* sk_value(X509_REVOKED* rev, int i)
+ {
+ return 0;
+ }
+
+
+ int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md,
+ const byte* salt, const byte* data, int sz, int count,
+ byte* key, byte* iv)
+ {
+ int keyLen = 0;
+ int ivLen = 0;
+
+ Md5 myMD;
+ byte digest[MD5_DIGEST_SIZE];
+
+ int j;
+ int keyLeft;
+ int ivLeft;
+ int keyOutput = 0;
+
+ InitMd5(&myMD);
+
+ /* only support MD5 for now */
+ if (XSTRNCMP(md, "MD5", 3)) return 0;
+
+ /* only support CBC DES and AES for now */
+ if (XSTRNCMP(type, "DES-CBC", 7) == 0) {
+ keyLen = DES_KEY_SIZE;
+ ivLen = DES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "DES-EDE3-CBC", 12) == 0) {
+ keyLen = DES3_KEY_SIZE;
+ ivLen = DES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "AES-128-CBC", 11) == 0) {
+ keyLen = AES_128_KEY_SIZE;
+ ivLen = AES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "AES-192-CBC", 11) == 0) {
+ keyLen = AES_192_KEY_SIZE;
+ ivLen = AES_IV_SIZE;
+ }
+ else if (XSTRNCMP(type, "AES-256-CBC", 11) == 0) {
+ keyLen = AES_256_KEY_SIZE;
+ ivLen = AES_IV_SIZE;
+ }
+ else
+ return 0;
+
+ keyLeft = keyLen;
+ ivLeft = ivLen;
+
+ while (keyOutput < (keyLen + ivLen)) {
+ int digestLeft = MD5_DIGEST_SIZE;
+ /* D_(i - 1) */
+ if (keyOutput) /* first time D_0 is empty */
+ Md5Update(&myMD, digest, MD5_DIGEST_SIZE);
+ /* data */
+ Md5Update(&myMD, data, sz);
+ /* salt */
+ if (salt)
+ Md5Update(&myMD, salt, EVP_SALT_SIZE);
+ Md5Final(&myMD, digest);
+ /* count */
+ for (j = 1; j < count; j++) {
+ Md5Update(&myMD, digest, MD5_DIGEST_SIZE);
+ Md5Final(&myMD, digest);
+ }
+
+ if (keyLeft) {
+ int store = min(keyLeft, MD5_DIGEST_SIZE);
+ XMEMCPY(&key[keyLen - keyLeft], digest, store);
+
+ keyOutput += store;
+ keyLeft -= store;
+ digestLeft -= store;
+ }
+
+ if (ivLeft && digestLeft) {
+ int store = min(ivLeft, digestLeft);
+ XMEMCPY(&iv[ivLen - ivLeft], &digest[MD5_DIGEST_SIZE -
+ digestLeft], store);
+ keyOutput += store;
+ ivLeft -= store;
+ }
+ }
+ if (keyOutput != (keyLen + ivLen))
+ return 0;
+ return keyOutput;
+ }
+
+ /* stunnel 4.28 needs */
+ void* SSL_CTX_get_ex_data(const SSL_CTX* ctx, int d)
+ {
+ return 0;
+ }
+
+
+ int SSL_CTX_set_ex_data(SSL_CTX* ctx, int d, void* p)
+ {
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_CTX_sess_set_get_cb(SSL_CTX* ctx, SSL_SESSION*(*f)(SSL*,
+ unsigned char*, int, int*))
+ {
+
+ }
+
+
+ void SSL_CTX_sess_set_new_cb(SSL_CTX* ctx, int (*f)(SSL*, SSL_SESSION*))
+ {
+
+ }
+
+
+ void SSL_CTX_sess_set_remove_cb(SSL_CTX* ctx, void (*f)(SSL_CTX*,
+ SSL_SESSION*))
+ {
+
+ }
+
+
+ int i2d_SSL_SESSION(SSL_SESSION* sess, unsigned char** p)
+ {
+ return sizeof(SSL_SESSION);
+ }
+
+
+ SSL_SESSION* d2i_SSL_SESSION(SSL_SESSION** sess, const unsigned char** p,
+ long i)
+ {
+ return *sess;
+ }
+
+
+ long SSL_SESSION_get_timeout(const SSL_SESSION* sess)
+ {
+ return sess->timeout;
+ }
+
+
+ long SSL_SESSION_get_time(const SSL_SESSION* sess)
+ {
+ return sess->bornOn;
+ }
+
+
+ int SSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, void* c)
+ {
+ return 0;
+ }
+
+
+#endif /* OPENSSL_EXTRA */
+
+
+#ifdef SESSION_CERTS
+
+
+/* Get peer's certificate chain */
+X509_CHAIN* CyaSSL_get_peer_chain(SSL* ssl)
+{
+ if (ssl)
+ return &ssl->session.chain;
+
+ return 0;
+}
+
+
+/* Get peer's certificate chain total count */
+int CyaSSL_get_chain_count(X509_CHAIN* chain)
+{
+ if (chain)
+ return chain->count;
+
+ return 0;
+}
+
+
+/* Get peer's ASN.1 DER ceritifcate at index (idx) length in bytes */
+int CyaSSL_get_chain_length(X509_CHAIN* chain, int idx)
+{
+ if (chain)
+ return chain->certs[idx].length;
+
+ return 0;
+}
+
+
+/* Get peer's ASN.1 DER ceritifcate at index (idx) */
+byte* CyaSSL_get_chain_cert(X509_CHAIN* chain, int idx)
+{
+ if (chain)
+ return chain->certs[idx].buffer;
+
+ return 0;
+}
+
+
+/* Get peer's PEM ceritifcate at index (idx), output to buffer if inLen big
+ enough else return error (-1), output length is in *outLen */
+int CyaSSL_get_chain_cert_pem(X509_CHAIN* chain, int idx,
+ unsigned char* buffer, int inLen, int* outLen)
+{
+ const char header[] = "-----BEGIN CERTIFICATE-----\n";
+ const char footer[] = "-----END CERTIFICATE-----\n";
+
+ int headerLen = sizeof(header) - 1;
+ int footerLen = sizeof(footer) - 1;
+ int i;
+
+ if (!chain || !outLen || !buffer)
+ return -1;
+
+ /* don't even try if inLen too short */
+ if (inLen < headerLen + footerLen + chain->certs[idx].length)
+ return -1;
+
+ /* header */
+ XMEMCPY(buffer, header, headerLen);
+ i = headerLen;
+
+ /* body */
+ *outLen = inLen; /* input to Base64Encode */
+ if (Base64Encode(chain->certs[idx].buffer, chain->certs[idx].length,
+ buffer + i, (word32*)outLen) < 0)
+ return -1;
+ i += *outLen;
+
+ /* footer */
+ if ( (i + footerLen) > inLen)
+ return -1;
+ XMEMCPY(buffer + i, footer, footerLen);
+ *outLen += headerLen + footerLen;
+
+ return 0;
+}
+
+
+/* get session ID */
+const byte* CyaSSL_get_sessionID(const SSL_SESSION* session)
+{
+ return session->sessionID;
+}
+
+
+#endif /* SESSION_CERTS */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ssl.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,675 @@
+/* ssl.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* ssl.h defines openssl compatibility layer
+ *
+ */
+
+
+
+#ifndef CYASSL_OPENSSL_H_
+#define CYASSL_OPENSSL_H_
+
+#include "os_settings.h" /* for users not using preprocessor flags */
+
+#ifndef NO_FILESYTEM
+ #include <stdio.h> /* ERR_print fp */
+#endif
+
+#ifdef YASSL_PREFIX
+ #include "prefix_ssl.h"
+#endif
+
+#undef X509_NAME /* wincrypt.h clash */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+typedef struct SSL SSL;
+typedef struct SSL_SESSION SSL_SESSION;
+typedef struct SSL_METHOD SSL_METHOD;
+typedef struct SSL_CTX SSL_CTX;
+
+typedef struct X509 X509;
+typedef struct X509_NAME X509_NAME;
+typedef struct X509_CHAIN X509_CHAIN;
+
+
+/* redeclare guard */
+#define SSL_TYPES_DEFINED
+
+
+
+
+typedef struct EVP_PKEY EVP_PKEY;
+typedef struct RSA RSA;
+typedef struct BIO BIO;
+typedef struct BIO_METHOD BIO_METHOD;
+typedef struct SSL_CIPHER SSL_CIPHER;
+typedef struct X509_LOOKUP X509_LOOKUP;
+typedef struct X509_LOOKUP_METHOD X509_LOOKUP_METHOD;
+typedef struct X509_CRL X509_CRL;
+typedef struct X509_EXTENSION X509_EXTENSION;
+typedef struct ASN1_TIME ASN1_TIME;
+typedef struct ASN1_INTEGER ASN1_INTEGER;
+typedef struct ASN1_OBJECT ASN1_OBJECT;
+typedef struct ASN1_STRING ASN1_STRING;
+typedef struct CRYPTO_dynlock_value CRYPTO_dynlock_value;
+
+#define ASN1_UTCTIME ASN1_TIME
+
+typedef struct MD4_CTX {
+ int buffer[32]; /* big enough to hold, check size in Init */
+} MD4_CTX;
+
+
+typedef struct COMP_METHOD {
+ int type; /* stunnel dereference */
+} COMP_METHOD;
+
+
+typedef struct X509_STORE {
+ int cache; /* stunnel dereference */
+} X509_STORE;
+
+
+typedef struct X509_REVOKED {
+ ASN1_INTEGER* serialNumber; /* stunnel dereference */
+} X509_REVOKED;
+
+
+typedef struct X509_OBJECT {
+ union {
+ char* ptr;
+ X509_CRL* crl; /* stunnel dereference */
+ } data;
+} X509_OBJECT;
+
+
+/* in cyassl_int.h too, change there !! */
+typedef struct X509_STORE_CTX {
+ int error;
+ int error_depth;
+ X509* current_cert; /* stunnel dereference */
+ char* domain; /* subject CN domain name */
+ /* in cyassl_int.h too, change there !! */
+} X509_STORE_CTX;
+
+
+SSL_METHOD *SSLv3_server_method(void);
+SSL_METHOD *SSLv3_client_method(void);
+SSL_METHOD *TLSv1_server_method(void);
+SSL_METHOD *TLSv1_client_method(void);
+SSL_METHOD *TLSv1_1_server_method(void);
+SSL_METHOD *TLSv1_1_client_method(void);
+SSL_METHOD *TLSv1_2_server_method(void);
+SSL_METHOD *TLSv1_2_client_method(void);
+
+#ifdef CYASSL_DTLS
+ SSL_METHOD *DTLSv1_client_method(void);
+ SSL_METHOD *DTLSv1_server_method(void);
+#endif
+
+#ifndef NO_FILESYSTEM
+
+int SSL_CTX_use_certificate_file(SSL_CTX*, const char*, int);
+int SSL_CTX_use_PrivateKey_file(SSL_CTX*, const char*, int);
+int SSL_CTX_load_verify_locations(SSL_CTX*, const char*, const char*);
+int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int);
+
+#ifdef CYASSL_DER_LOAD
+ int CyaSSL_CTX_load_verify_locations(SSL_CTX*, const char*, int);
+#endif
+
+#ifdef HAVE_NTRU
+ int CyaSSL_CTX_use_NTRUPrivateKey_file(SSL_CTX*, const char*); /* load NTRU
+ private key blob */
+#endif
+
+int CyaSSL_PemCertToDer(const char*, unsigned char*, int);
+
+#endif /* NO_FILESYSTEM */
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD*);
+SSL* SSL_new(SSL_CTX*);
+int SSL_set_fd (SSL*, int);
+int SSL_get_fd(const SSL*);
+int SSL_connect(SSL*); /* please see note at top of README
+ if you get an error from connect */
+int SSL_write(SSL*, const void*, int);
+int SSL_read(SSL*, void*, int);
+int SSL_accept(SSL*);
+void SSL_CTX_free(SSL_CTX*);
+void SSL_free(SSL*);
+int SSL_shutdown(SSL*);
+
+void SSL_CTX_set_quiet_shutdown(SSL_CTX*, int);
+
+int SSL_get_error(SSL*, int);
+
+int SSL_set_session(SSL *ssl, SSL_SESSION *session);
+SSL_SESSION* SSL_get_session(SSL* ssl);
+void SSL_flush_sessions(SSL_CTX *ctx, long tm);
+
+
+typedef int (*VerifyCallback)(int, X509_STORE_CTX*);
+typedef int (*pem_password_cb)(char*, int, int, void*);
+
+void SSL_CTX_set_verify(SSL_CTX*, int, VerifyCallback verify_callback);
+
+
+int SSL_pending(SSL*);
+
+
+void SSL_load_error_strings(void);
+int SSL_library_init(void);
+long SSL_CTX_set_session_cache_mode(SSL_CTX*, long);
+
+/* only supports full name from cipher_name[] delimited by : */
+int SSL_CTX_set_cipher_list(SSL_CTX*, const char*);
+
+char* ERR_error_string(unsigned long,char*);
+void ERR_error_string_n(unsigned long e, char *buf, size_t len);
+
+
+/* extras */
+
+#define STACK_OF(x) x
+
+int SSL_set_ex_data(SSL*, int, void*);
+int SSL_get_shutdown(const SSL*);
+int SSL_set_rfd(SSL*, int);
+int SSL_set_wfd(SSL*, int);
+void SSL_set_shutdown(SSL*, int);
+int SSL_set_session_id_context(SSL*, const unsigned char*, unsigned int);
+void SSL_set_connect_state(SSL*);
+void SSL_set_accept_state(SSL*);
+int SSL_session_reused(SSL*);
+void SSL_SESSION_free(SSL_SESSION* session);
+
+const char* SSL_get_version(SSL*);
+SSL_CIPHER* SSL_get_current_cipher(SSL*);
+char* SSL_CIPHER_description(SSL_CIPHER*, char*, int);
+const char* SSL_CIPHER_get_name(const SSL_CIPHER* cipher);
+SSL_SESSION* SSL_get1_session(SSL* ssl); /* what's ref count */
+
+void X509_free(X509*);
+void OPENSSL_free(void*);
+
+int OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl);
+
+SSL_METHOD* SSLv23_client_method(void);
+SSL_METHOD* SSLv2_client_method(void);
+SSL_METHOD* SSLv2_server_method(void);
+
+void MD4_Init(MD4_CTX*);
+void MD4_Update(MD4_CTX*, const void*, size_t);
+void MD4_Final(unsigned char*, MD4_CTX*);
+
+BIO* BIO_new(BIO_METHOD*);
+int BIO_free(BIO*);
+int BIO_free_all(BIO*);
+int BIO_read(BIO*, void*, int);
+int BIO_write(BIO*, const void*, int);
+BIO* BIO_push(BIO*, BIO* append);
+BIO* BIO_pop(BIO*);
+int BIO_flush(BIO*);
+int BIO_pending(BIO*);
+
+BIO_METHOD* BIO_f_buffer(void);
+long BIO_set_write_buffer_size(BIO*, long size);
+BIO_METHOD* BIO_f_ssl(void);
+BIO* BIO_new_socket(int sfd, int flag);
+void SSL_set_bio(SSL*, BIO* rd, BIO* wr);
+int BIO_eof(BIO*);
+long BIO_set_ssl(BIO*, SSL*, int flag);
+
+BIO_METHOD* BIO_s_mem(void);
+BIO_METHOD* BIO_f_base64(void);
+void BIO_set_flags(BIO*, int);
+
+void OpenSSL_add_all_algorithms(void);
+int SSLeay_add_ssl_algorithms(void);
+int SSLeay_add_all_algorithms(void);
+
+void RAND_screen(void);
+const char* RAND_file_name(char*, size_t);
+int RAND_write_file(const char*);
+int RAND_load_file(const char*, long);
+int RAND_egd(const char*);
+
+COMP_METHOD* COMP_zlib(void);
+COMP_METHOD* COMP_rle(void);
+int SSL_COMP_add_compression_method(int, void*);
+
+int SSL_get_ex_new_index(long, void*, void*, void*, void*);
+
+void CRYPTO_set_id_callback(unsigned long (*f)(void));
+void CRYPTO_set_locking_callback(void (*f)(int, int, const char*, int));
+void CRYPTO_set_dynlock_create_callback(CRYPTO_dynlock_value* (*f)(const char*,
+ int));
+void CRYPTO_set_dynlock_lock_callback(void (*f)(int, CRYPTO_dynlock_value*,
+ const char*, int));
+void CRYPTO_set_dynlock_destroy_callback(void (*f)(CRYPTO_dynlock_value*,
+ const char*, int));
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX*);
+
+char* X509_NAME_oneline(X509_NAME*, char*, int);
+X509_NAME* X509_get_issuer_name(X509*);
+X509_NAME* X509_get_subject_name(X509*);
+const char* X509_verify_cert_error_string(long);
+
+int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long);
+int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long);
+X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD* X509_LOOKUP_file(void);
+
+X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*);
+X509_STORE* X509_STORE_new(void);
+int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*,
+ X509_OBJECT*);
+int X509_STORE_CTX_init(X509_STORE_CTX*, X509_STORE*, X509*, STACK_OF(X509)*);
+void X509_STORE_CTX_cleanup(X509_STORE_CTX*);
+
+ASN1_TIME* X509_CRL_get_lastUpdate(X509_CRL*);
+ASN1_TIME* X509_CRL_get_nextUpdate(X509_CRL*);
+
+EVP_PKEY* X509_get_pubkey(X509*);
+int X509_CRL_verify(X509_CRL*, EVP_PKEY*);
+void X509_STORE_CTX_set_error(X509_STORE_CTX*, int);
+void X509_OBJECT_free_contents(X509_OBJECT*);
+void EVP_PKEY_free(EVP_PKEY*);
+int X509_cmp_current_time(const ASN1_TIME*);
+int sk_X509_REVOKED_num(X509_REVOKED*);
+
+X509_REVOKED* X509_CRL_get_REVOKED(X509_CRL*);
+X509_REVOKED* sk_X509_REVOKED_value(X509_REVOKED*, int);
+
+ASN1_INTEGER* X509_get_serialNumber(X509*);
+
+int ASN1_TIME_print(BIO*, const ASN1_TIME*);
+
+int ASN1_INTEGER_cmp(const ASN1_INTEGER*, const ASN1_INTEGER*);
+long ASN1_INTEGER_get(const ASN1_INTEGER*);
+
+STACK_OF(X509_NAME)* SSL_load_client_CA_file(const char*);
+
+void SSL_CTX_set_client_CA_list(SSL_CTX*, STACK_OF(X509_NAME)*);
+void* X509_STORE_CTX_get_ex_data(X509_STORE_CTX*, int);
+int SSL_get_ex_data_X509_STORE_CTX_idx(void);
+void* SSL_get_ex_data(const SSL*, int);
+
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata);
+void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb);
+
+
+long SSL_CTX_set_timeout(SSL_CTX*, long);
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)());
+
+unsigned long ERR_peek_error(void);
+int ERR_GET_REASON(int);
+
+char* SSL_alert_type_string_long(int);
+char* SSL_alert_desc_string_long(int);
+char* SSL_state_string_long(SSL*);
+
+void RSA_free(RSA*);
+RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*);
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int));
+
+int PEM_def_callback(char*, int num, int w, void* key);
+
+long SSL_CTX_sess_accept(SSL_CTX*);
+long SSL_CTX_sess_connect(SSL_CTX*);
+long SSL_CTX_sess_accept_good(SSL_CTX*);
+long SSL_CTX_sess_connect_good(SSL_CTX*);
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_hits(SSL_CTX*);
+long SSL_CTX_sess_cb_hits(SSL_CTX*);
+long SSL_CTX_sess_cache_full(SSL_CTX*);
+long SSL_CTX_sess_misses(SSL_CTX*);
+long SSL_CTX_sess_timeouts(SSL_CTX*);
+long SSL_CTX_sess_number(SSL_CTX*);
+long SSL_CTX_sess_get_cache_size(SSL_CTX*);
+
+
+#define SSL_DEFAULT_CIPHER_LIST "" /* default all */
+#define RSA_F4 0x10001L
+
+enum {
+ OCSP_NOCERTS = 1,
+ OCSP_NOINTERN = 2,
+ OCSP_NOSIGS = 4,
+ OCSP_NOCHAIN = 8,
+ OCSP_NOVERIFY = 16,
+ OCSP_NOEXPLICIT = 32,
+ OCSP_NOCASIGN = 64,
+ OCSP_NODELEGATED = 128,
+ OCSP_NOCHECKS = 256,
+ OCSP_TRUSTOTHER = 512,
+ OCSP_RESPID_KEY = 1024,
+ OCSP_NOTIME = 2048,
+
+ OCSP_CERTID = 2,
+ OCSP_REQUEST = 4,
+ OCSP_RESPONSE = 8,
+ OCSP_BASICRESP = 16,
+
+ ASN1_GENERALIZEDTIME = 4,
+
+ SSL_OP_MICROSOFT_SESS_ID_BUG = 1,
+ SSL_OP_NETSCAPE_CHALLENGE_BUG = 2,
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 3,
+ SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 4,
+ SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 5,
+ SSL_OP_MSIE_SSLV2_RSA_PADDING = 6,
+ SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 7,
+ SSL_OP_TLS_D5_BUG = 8,
+ SSL_OP_TLS_BLOCK_PADDING_BUG = 9,
+ SSL_OP_TLS_ROLLBACK_BUG = 10,
+ SSL_OP_ALL = 11,
+ SSL_OP_EPHEMERAL_RSA = 12,
+ SSL_OP_NO_SSLv3 = 13,
+ SSL_OP_NO_TLSv1 = 14,
+ SSL_OP_PKCS1_CHECK_1 = 15,
+ SSL_OP_PKCS1_CHECK_2 = 16,
+ SSL_OP_NETSCAPE_CA_DN_BUG = 17,
+ SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 18,
+ SSL_OP_SINGLE_DH_USE = 19,
+ SSL_OP_NO_TICKET = 20,
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 21,
+ SSL_OP_NO_QUERY_MTU = 22,
+ SSL_OP_COOKIE_EXCHANGE = 23,
+ SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 24,
+ SSL_OP_SINGLE_ECDH_USE = 25,
+ SSL_OP_CIPHER_SERVER_PREFERENCE = 26,
+
+ SSL_MAX_SSL_SESSION_ID_LENGTH = 32,
+
+ EVP_R_BAD_DECRYPT = 2,
+
+ SSL_CB_LOOP = 4,
+ SSL_ST_CONNECT = 5,
+ SSL_ST_ACCEPT = 6,
+ SSL_CB_ALERT = 7,
+ SSL_CB_READ = 8,
+ SSL_CB_HANDSHAKE_DONE = 9,
+
+ SSL_MODE_ENABLE_PARTIAL_WRITE = 2,
+
+ BIO_FLAGS_BASE64_NO_NL = 1,
+ BIO_CLOSE = 1,
+ BIO_NOCLOSE = 0,
+
+ NID_undef = 0,
+
+ X509_FILETYPE_PEM = 8,
+ X509_LU_X509 = 9,
+ X509_LU_CRL = 12,
+
+ X509_V_ERR_CRL_SIGNATURE_FAILURE = 13,
+ X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14,
+ X509_V_ERR_CRL_HAS_EXPIRED = 15,
+ X509_V_ERR_CERT_REVOKED = 16,
+ X509_V_ERR_CERT_CHAIN_TOO_LONG = 17,
+ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18,
+ X509_V_ERR_CERT_NOT_YET_VALID = 19,
+ X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20,
+ X509_V_ERR_CERT_HAS_EXPIRED = 21,
+ X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22,
+
+ X509_V_OK = 0,
+
+ CRYPTO_LOCK = 1,
+ CRYPTO_NUM_LOCKS = 10,
+
+};
+
+/* extras end */
+
+#ifndef NO_FILESYSTEM
+/* CyaSSL extension, provide last error from SSL_get_error
+ since not using thread storage error queue */
+void ERR_print_errors_fp(FILE*, int err);
+#endif
+
+enum { /* ssl Constants */
+ SSL_ERROR_NONE = 0, /* for most functions */
+ SSL_FAILURE = 0, /* for some functions */
+ SSL_SUCCESS = 1,
+
+ SSL_BAD_CERTTYPE = -8,
+ SSL_BAD_STAT = -7,
+ SSL_BAD_PATH = -6,
+ SSL_BAD_FILETYPE = -5,
+ SSL_BAD_FILE = -4,
+ SSL_NOT_IMPLEMENTED = -3,
+ SSL_UNKNOWN = -2,
+ SSL_FATAL_ERROR = -1,
+
+ SSL_FILETYPE_ASN1 = 2,
+ SSL_FILETYPE_PEM = 1,
+ SSL_FILETYPE_DEFAULT = 2, /* ASN1 */
+ SSL_FILETYPE_RAW = 3, /* NTRU raw key blob */
+
+ SSL_VERIFY_NONE = 0,
+ SSL_VERIFY_PEER = 1,
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2,
+ SSL_VERIFY_CLIENT_ONCE = 4,
+
+ SSL_SESS_CACHE_OFF = 30,
+ SSL_SESS_CACHE_CLIENT = 31,
+ SSL_SESS_CACHE_SERVER = 32,
+ SSL_SESS_CACHE_BOTH = 33,
+ SSL_SESS_CACHE_NO_AUTO_CLEAR = 34,
+ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35,
+
+ SSL_ERROR_WANT_READ = 2,
+ SSL_ERROR_WANT_WRITE = 3,
+ SSL_ERROR_WANT_CONNECT = 7,
+ SSL_ERROR_WANT_ACCEPT = 8,
+ SSL_ERROR_SYSCALL = 5,
+ SSL_ERROR_WANT_X509_LOOKUP = 83,
+ SSL_ERROR_ZERO_RETURN = 6,
+ SSL_ERROR_SSL = 85,
+
+ SSL_SENT_SHUTDOWN = 1,
+ SSL_RECEIVED_SHUTDOWN = 2,
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4,
+ SSL_OP_NO_SSLv2 = 8,
+
+ SSL_R_SSL_HANDSHAKE_FAILURE = 101,
+ SSL_R_TLSV1_ALERT_UNKNOWN_CA = 102,
+ SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103,
+ SSL_R_SSLV3_ALERT_BAD_CERTIFICATE = 104,
+
+ PEM_BUFSIZE = 1024,
+};
+
+
+#ifndef NO_PSK
+ typedef unsigned int (*psk_client_callback)(SSL*, const char*, char*,
+ unsigned int, unsigned char*, unsigned int);
+ void SSL_CTX_set_psk_client_callback(SSL_CTX*, psk_client_callback);
+ void SSL_set_psk_client_callback(SSL*, psk_client_callback);
+
+ const char* SSL_get_psk_identity_hint(const SSL*);
+ const char* SSL_get_psk_identity(const SSL*);
+
+ int SSL_CTX_use_psk_identity_hint(SSL_CTX*, const char*);
+ int SSL_use_psk_identity_hint(SSL*, const char*);
+
+ typedef unsigned int (*psk_server_callback)(SSL*, const char*,
+ unsigned char*, unsigned int);
+ void SSL_CTX_set_psk_server_callback(SSL_CTX*, psk_server_callback);
+ void SSL_set_psk_server_callback(SSL*, psk_server_callback);
+
+ #define PSK_TYPES_DEFINED
+#endif /* NO_PSK */
+
+
+/* extra begins */
+
+enum { /* ERR Constants */
+ ERR_TXT_STRING = 1,
+};
+
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *);
+
+unsigned long ERR_get_error(void);
+void ERR_clear_error(void);
+
+
+int RAND_status(void);
+int RAND_bytes(unsigned char* buf, int num);
+SSL_METHOD *SSLv23_server_method(void);
+long SSL_CTX_set_options(SSL_CTX*, long);
+int SSL_CTX_check_private_key(SSL_CTX*);
+
+
+void ERR_free_strings(void);
+void ERR_remove_state(unsigned long);
+void EVP_cleanup(void);
+
+void CRYPTO_cleanup_all_ex_data(void);
+long SSL_CTX_set_mode(SSL_CTX* ctx, long mode);
+long SSL_CTX_get_mode(SSL_CTX* ctx);
+void SSL_CTX_set_default_read_ahead(SSL_CTX* ctx, int m);
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX*, long);
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX*);
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int);
+
+X509* SSL_get_peer_certificate(SSL* ssl);
+
+int SSL_want_read(SSL*);
+int SSL_want_write(SSL*);
+
+int BIO_printf(BIO*, const char*, ...);
+int ASN1_UTCTIME_print(BIO*, const ASN1_UTCTIME*);
+
+int sk_num(X509_REVOKED*);
+void* sk_value(X509_REVOKED*, int);
+
+/* stunnel 4.28 needs */
+void* SSL_CTX_get_ex_data(const SSL_CTX*, int);
+int SSL_CTX_set_ex_data(SSL_CTX*, int, void*);
+void SSL_CTX_sess_set_get_cb(SSL_CTX*, SSL_SESSION*(*f)(SSL*, unsigned char*,
+ int, int*));
+void SSL_CTX_sess_set_new_cb(SSL_CTX*, int (*f)(SSL*, SSL_SESSION*));
+void SSL_CTX_sess_set_remove_cb(SSL_CTX*, void (*f)(SSL_CTX*, SSL_SESSION*));
+
+int i2d_SSL_SESSION(SSL_SESSION*, unsigned char**);
+SSL_SESSION* d2i_SSL_SESSION(SSL_SESSION**,const unsigned char**, long);
+
+long SSL_SESSION_get_timeout(const SSL_SESSION*);
+long SSL_SESSION_get_time(const SSL_SESSION*);
+int SSL_CTX_get_ex_new_index(long, void*, void*, void*, void*);
+
+/* extra ends */
+
+
+/* CyaSSL extensions */
+
+/* call before SSL_connect, if verifying will add name check to
+ date check and signature check */
+int CyaSSL_check_domain_name(SSL* ssl, const char* dn);
+
+int InitCyaSSL(void); /* need to call once to load library (session cache) */
+int FreeCyaSSL(void); /* call when done to free session cache mutex */
+
+int CyaSSL_Debugging_ON(void); /* turn logging on, only if compiled in */
+void CyaSSL_Debugging_OFF(void); /* turn logging off */
+
+int CyaSSL_set_compression(SSL* ssl); /* turn on CyaSSL data compression */
+
+int CyaSSL_CTX_use_NTRUPrivateKey_file(SSL_CTX*, const char*); /* load NTRU
+ private key blob */
+X509_CHAIN* CyaSSL_get_peer_chain(SSL* ssl); /* get CyaSSL peer X509_CHAIN */
+int CyaSSL_get_chain_count(X509_CHAIN* chain); /* peer chain count */
+int CyaSSL_get_chain_length(X509_CHAIN*, int idx); /* index cert length */
+unsigned char* CyaSSL_get_chain_cert(X509_CHAIN*, int idx); /* index cert */
+int CyaSSL_get_chain_cert_pem(X509_CHAIN*, int idx, unsigned char* buffer,
+ int inLen, int* outLen); /* get index cert in PEM */
+const unsigned char* CyaSSL_get_sessionID(const SSL_SESSION* session);
+
+#ifndef _WIN32
+ #ifndef NO_WRITEV
+ #include <sys/uio.h>
+ /* allow writev style writing */
+ int CyaSSL_writev(SSL* ssl, const struct iovec* iov, int iovcnt);
+ #endif
+#endif
+
+#if defined(NO_FILESYSTEM) || defined(MICRIUM)
+
+int CyaSSL_CTX_load_verify_buffer(SSL_CTX*, const unsigned char*, long, int);
+int CyaSSL_CTX_use_certificate_buffer(SSL_CTX*, const unsigned char*, long,int);
+int CyaSSL_CTX_use_PrivateKey_buffer(SSL_CTX*, const unsigned char*, long, int);
+int CyaSSL_CTX_use_certificate_chain_buffer(SSL_CTX*,const unsigned char*,long);
+
+#endif /* NO_FILESYSTEM || MICRIUM */
+
+
+/* I/O callbacks */
+typedef int (*CallbackIORecv)(char *buf, int sz, void *ctx);
+typedef int (*CallbackIOSend)(char *buf, int sz, void *ctx);
+
+void CyaSSL_SetIORecv(SSL_CTX*, CallbackIORecv);
+void CyaSSL_SetIOSend(SSL_CTX*, CallbackIOSend);
+
+void CyaSSL_SetIOReadCtx(SSL* ssl, void *ctx);
+void CyaSSL_SetIOWriteCtx(SSL* ssl, void *ctx);
+
+
+#ifdef CYASSL_CALLBACKS
+
+/* used internally by CyaSSL while OpenSSL types aren't */
+#include "cyassl_callbacks.h"
+
+typedef int (*HandShakeCallBack)(HandShakeInfo*);
+typedef int (*TimeoutCallBack)(TimeoutInfo*);
+
+/* CyaSSL connect extension allowing HandShakeCallBack and/or TimeoutCallBack
+ for diagnostics */
+int CyaSSL_connect_ex(SSL*, HandShakeCallBack, TimeoutCallBack, Timeval);
+int CyaSSL_accept_ex(SSL*, HandShakeCallBack, TimeoutCallBack, Timeval);
+
+#endif /* CYASSL_CALLBACKS */
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* CyaSSL_openssl_h__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tfm.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,651 @@
+/* tfm.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+/*
+ * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca,
+ * http://math.libtomcrypt.com
+ */
+
+
+/**
+ * Edited by Moisés Guimarães (moises.guimaraes@phoebus.com.br)
+ * to fit CyaSSL's needs.
+ */
+
+
+#ifndef CTAO_CRYPT_TFM_H
+#define CTAO_CRYPT_TFM_H
+
+#include "types.h"
+#ifndef CHAR_BIT
+ #include <limits.h>
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifndef MIN
+ #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+ #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+/* externally define this symbol to ignore the default settings, useful for changing the build from the make process */
+#ifndef TFM_ALREADY_SET
+
+/* do we want the large set of small multiplications ?
+ Enable these if you are going to be doing a lot of small (<= 16 digit) multiplications say in ECC
+ Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-)
+ */
+/* need to refactor the function */
+/*#define TFM_SMALL_SET */
+
+/* do we want huge code
+ Enable these if you are doing 20, 24, 28, 32, 48, 64 digit multiplications (useful for RSA)
+ Less important on 64-bit machines as 32 digits == 2048 bits
+ */
+#if 0
+#define TFM_MUL3
+#define TFM_MUL4
+#define TFM_MUL6
+#define TFM_MUL7
+#define TFM_MUL8
+#define TFM_MUL9
+#define TFM_MUL12
+#define TFM_MUL17
+#endif
+#ifdef TFM_SMALL_SET
+#define TFM_MUL20
+#define TFM_MUL24
+#define TFM_MUL28
+#define TFM_MUL32
+#define TFM_MUL48
+#define TFM_MUL64
+#endif
+
+#if 0
+#define TFM_SQR3
+#define TFM_SQR4
+#define TFM_SQR6
+#define TFM_SQR7
+#define TFM_SQR8
+#define TFM_SQR9
+#define TFM_SQR12
+#define TFM_SQR17
+#endif
+#ifdef TFM_SMALL_SET
+#define TFM_SQR20
+#define TFM_SQR24
+#define TFM_SQR28
+#define TFM_SQR32
+#define TFM_SQR48
+#define TFM_SQR64
+#endif
+
+/* do we want some overflow checks
+ Not required if you make sure your numbers are within range (e.g. by default a modulus for fp_exptmod() can only be upto 2048 bits long)
+ */
+/* #define TFM_CHECK */
+
+/* Is the target a P4 Prescott
+ */
+/* #define TFM_PRESCOTT */
+
+/* Do we want timing resistant fp_exptmod() ?
+ * This makes it slower but also timing invariant with respect to the exponent
+ */
+/* #define TFM_TIMING_RESISTANT */
+
+#endif
+
+/* Max size of any number in bits. Basically the largest size you will be multiplying
+ * should be half [or smaller] of FP_MAX_SIZE-four_digit
+ *
+ * You can externally define this or it defaults to 4096-bits [allowing multiplications upto 2048x2048 bits ]
+ */
+#ifndef FP_MAX_SIZE
+ #define FP_MAX_SIZE (4096+(8*DIGIT_BIT))
+#endif
+
+/* will this lib work? */
+#if (CHAR_BIT & 7)
+ #error CHAR_BIT must be a multiple of eight.
+#endif
+#if FP_MAX_SIZE % CHAR_BIT
+ #error FP_MAX_SIZE must be a multiple of CHAR_BIT
+#endif
+
+/* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */
+#if defined(__x86_64__)
+ #if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)
+ #error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid!
+ #endif
+ #if !defined(TFM_X86_64) && !defined(TFM_NO_ASM)
+ #define TFM_X86_64
+ #endif
+#endif
+#if defined(TFM_X86_64)
+ #if !defined(FP_64BIT)
+ #define FP_64BIT
+ #endif
+#endif
+
+/* try to detect x86-32 */
+#if defined(__i386__) && !defined(TFM_SSE2)
+ #if defined(TFM_X86_64) || defined(TFM_ARM)
+ #error x86-32 detected, x86-64/ARM optimizations are not valid!
+ #endif
+ #if !defined(TFM_X86) && !defined(TFM_NO_ASM)
+ #define TFM_X86
+ #endif
+#endif
+
+/* make sure we're 32-bit for x86-32/sse/arm/ppc32 */
+#if (defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) || defined(TFM_PPC32)) && defined(FP_64BIT)
+ #warning x86-32, SSE2 and ARM, PPC32 optimizations require 32-bit digits (undefining)
+ #undef FP_64BIT
+#endif
+
+/* multi asms? */
+#ifdef TFM_X86
+ #define TFM_ASM
+#endif
+#ifdef TFM_X86_64
+ #ifdef TFM_ASM
+ #error TFM_ASM already defined!
+ #endif
+ #define TFM_ASM
+#endif
+#ifdef TFM_SSE2
+ #ifdef TFM_ASM
+ #error TFM_ASM already defined!
+ #endif
+ #define TFM_ASM
+#endif
+#ifdef TFM_ARM
+ #ifdef TFM_ASM
+ #error TFM_ASM already defined!
+ #endif
+ #define TFM_ASM
+#endif
+#ifdef TFM_PPC32
+ #ifdef TFM_ASM
+ #error TFM_ASM already defined!
+ #endif
+ #define TFM_ASM
+#endif
+#ifdef TFM_PPC64
+ #ifdef TFM_ASM
+ #error TFM_ASM already defined!
+ #endif
+ #define TFM_ASM
+#endif
+#ifdef TFM_AVR32
+ #ifdef TFM_ASM
+ #error TFM_ASM already defined!
+ #endif
+ #define TFM_ASM
+#endif
+
+/* we want no asm? */
+#ifdef TFM_NO_ASM
+ #undef TFM_X86
+ #undef TFM_X86_64
+ #undef TFM_SSE2
+ #undef TFM_ARM
+ #undef TFM_PPC32
+ #undef TFM_PPC64
+ #undef TFM_AVR32
+ #undef TFM_ASM
+#endif
+
+/* ECC helpers */
+#ifdef TFM_ECC192
+ #ifdef FP_64BIT
+ #define TFM_MUL3
+ #define TFM_SQR3
+ #else
+ #define TFM_MUL6
+ #define TFM_SQR6
+ #endif
+#endif
+
+#ifdef TFM_ECC224
+ #ifdef FP_64BIT
+ #define TFM_MUL4
+ #define TFM_SQR4
+ #else
+ #define TFM_MUL7
+ #define TFM_SQR7
+ #endif
+#endif
+
+#ifdef TFM_ECC256
+ #ifdef FP_64BIT
+ #define TFM_MUL4
+ #define TFM_SQR4
+ #else
+ #define TFM_MUL8
+ #define TFM_SQR8
+ #endif
+#endif
+
+#ifdef TFM_ECC384
+ #ifdef FP_64BIT
+ #define TFM_MUL6
+ #define TFM_SQR6
+ #else
+ #define TFM_MUL12
+ #define TFM_SQR12
+ #endif
+#endif
+
+#ifdef TFM_ECC521
+ #ifdef FP_64BIT
+ #define TFM_MUL9
+ #define TFM_SQR9
+ #else
+ #define TFM_MUL17
+ #define TFM_SQR17
+ #endif
+#endif
+
+
+/* some default configurations.
+ */
+#if defined(FP_64BIT)
+ /* for GCC only on supported platforms */
+#ifndef CRYPT
+ typedef unsigned long ulong64;
+#endif
+ typedef ulong64 fp_digit;
+ typedef unsigned long fp_word __attribute__ ((mode(TI)));
+#else
+ /* 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 fp_digit;
+ typedef ulong64 fp_word;
+#endif
+
+/* # of digits this is */
+#define DIGIT_BIT (int)((CHAR_BIT) * sizeof(fp_digit))
+#define FP_MASK (fp_digit)(-1)
+#define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT)
+
+/* signs */
+#define FP_ZPOS 0
+#define FP_NEG 1
+
+/* return codes */
+#define FP_OKAY 0
+#define FP_VAL 1
+#define FP_MEM 2
+
+/* equalities */
+#define FP_LT -1 /* less than */
+#define FP_EQ 0 /* equal to */
+#define FP_GT 1 /* greater than */
+
+/* replies */
+#define FP_YES 1 /* yes response */
+#define FP_NO 0 /* no response */
+
+/* a FP type */
+typedef struct {
+ fp_digit dp[FP_SIZE];
+ int used,
+ sign;
+} fp_int;
+
+/* functions */
+
+/* returns a TFM ident string useful for debugging... */
+/*const char *fp_ident(void);*/
+
+/* initialize [or zero] an fp int */
+#define fp_init(a) (void)XMEMSET((a), 0, sizeof(fp_int))
+#define fp_zero(a) fp_init(a)
+
+/* zero/even/odd ? */
+#define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO)
+#define fp_iseven(a) (((a)->used >= 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO)
+#define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO)
+
+/* set to a small digit */
+void fp_set(fp_int *a, fp_digit b);
+
+/* copy from a to b */
+#define fp_copy(a, b) (void)(((a) != (b)) ? (XMEMCPY((b), (a), sizeof(fp_int))) : (void)0)
+#define fp_init_copy(a, b) fp_copy(b, a)
+
+/* clamp digits */
+#define fp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; }
+
+/* negate and absolute */
+#define fp_neg(a, b) { fp_copy(a, b); (b)->sign ^= 1; fp_clamp(b); }
+#define fp_abs(a, b) { fp_copy(a, b); (b)->sign = 0; }
+
+/* right shift x digits */
+void fp_rshd(fp_int *a, int x);
+
+/* left shift x digits */
+void fp_lshd(fp_int *a, int x);
+
+/* signed comparison */
+int fp_cmp(fp_int *a, fp_int *b);
+
+/* unsigned comparison */
+int fp_cmp_mag(fp_int *a, fp_int *b);
+
+/* power of 2 operations */
+void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
+void fp_mod_2d(fp_int *a, int b, fp_int *c);
+void fp_mul_2d(fp_int *a, int b, fp_int *c);
+void fp_2expt (fp_int *a, int b);
+void fp_mul_2(fp_int *a, fp_int *c);
+void fp_div_2(fp_int *a, fp_int *c);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+/*int fp_cnt_lsb(fp_int *a);*/
+
+/* c = a + b */
+void fp_add(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = a - b */
+void fp_sub(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = a * b */
+void fp_mul(fp_int *a, fp_int *b, fp_int *c);
+
+/* b = a*a */
+void fp_sqr(fp_int *a, fp_int *b);
+
+/* a/b => cb + d == a */
+int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* c = a mod b, 0 <= c < b */
+int fp_mod(fp_int *a, fp_int *b, fp_int *c);
+
+/* compare against a single digit */
+int fp_cmp_d(fp_int *a, fp_digit b);
+
+/* c = a + b */
+/*void fp_add_d(fp_int *a, fp_digit b, fp_int *c);*/
+
+/* c = a - b */
+/*void fp_sub_d(fp_int *a, fp_digit b, fp_int *c);*/
+
+/* c = a * b */
+void fp_mul_d(fp_int *a, fp_digit b, fp_int *c);
+
+/* a/b => cb + d == a */
+/*int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d);*/
+
+/* c = a mod b, 0 <= c < b */
+/*int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c);*/
+
+/* ---> number theory <--- */
+/* d = a + b (mod c) */
+/*int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);*/
+
+/* d = a - b (mod c) */
+/*int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);*/
+
+/* d = a * b (mod c) */
+int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* c = a * a (mod b) */
+/*int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c);*/
+
+/* c = 1/a (mod b) */
+int fp_invmod(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = (a, b) */
+/*void fp_gcd(fp_int *a, fp_int *b, fp_int *c);*/
+
+/* c = [a, b] */
+/*void fp_lcm(fp_int *a, fp_int *b, fp_int *c);*/
+
+/* setups the montgomery reduction */
+int fp_montgomery_setup(fp_int *a, fp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+void fp_montgomery_calc_normalization(fp_int *a, fp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp);
+
+/* d = a**b (mod c) */
+int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* primality stuff */
+
+/* perform a Miller-Rabin test of a to the base b and store result in "result" */
+/*void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result);*/
+
+/* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime */
+/*int fp_isprime(fp_int *a);*/
+
+/* Primality generation flags */
+/*#define TFM_PRIME_BBS 0x0001 */ /* BBS style prime */
+/*#define TFM_PRIME_SAFE 0x0002 */ /* Safe prime (p-1)/2 == prime */
+/*#define TFM_PRIME_2MSB_OFF 0x0004 */ /* force 2nd MSB to 0 */
+/*#define TFM_PRIME_2MSB_ON 0x0008 */ /* force 2nd MSB to 1 */
+
+/* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+/*typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);*/
+
+/*#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)*/
+
+/*int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);*/
+
+/* radix conersions */
+int fp_count_bits(fp_int *a);
+
+int fp_unsigned_bin_size(fp_int *a);
+void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c);
+void fp_to_unsigned_bin(fp_int *a, unsigned char *b);
+
+/*int fp_signed_bin_size(fp_int *a);*/
+/*void fp_read_signed_bin(fp_int *a, unsigned char *b, int c);*/
+/*void fp_to_signed_bin(fp_int *a, unsigned char *b);*/
+
+/*int fp_read_radix(fp_int *a, char *str, int radix);*/
+/*int fp_toradix(fp_int *a, char *str, int radix);*/
+/*int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen);*/
+
+
+/* VARIOUS LOW LEVEL STUFFS */
+void s_fp_add(fp_int *a, fp_int *b, fp_int *c);
+void s_fp_sub(fp_int *a, fp_int *b, fp_int *c);
+void fp_reverse(unsigned char *s, int len);
+
+void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C);
+
+#ifdef TFM_SMALL_SET
+void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C);
+#endif
+
+#ifdef TFM_MUL3
+void fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL4
+void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL6
+void fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL7
+void fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL8
+void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL9
+void fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL12
+void fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL17
+void fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C);
+#endif
+
+#ifdef TFM_MUL20
+void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL24
+void fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL28
+void fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL32
+void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL48
+void fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_MUL64
+void fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C);
+#endif
+
+void fp_sqr_comba(fp_int *A, fp_int *B);
+
+#ifdef TFM_SMALL_SET
+void fp_sqr_comba_small(fp_int *A, fp_int *B);
+#endif
+
+#ifdef TFM_SQR3
+void fp_sqr_comba3(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR4
+void fp_sqr_comba4(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR6
+void fp_sqr_comba6(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR7
+void fp_sqr_comba7(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR8
+void fp_sqr_comba8(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR9
+void fp_sqr_comba9(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR12
+void fp_sqr_comba12(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR17
+void fp_sqr_comba17(fp_int *A, fp_int *B);
+#endif
+
+#ifdef TFM_SQR20
+void fp_sqr_comba20(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR24
+void fp_sqr_comba24(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR28
+void fp_sqr_comba28(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR32
+void fp_sqr_comba32(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR48
+void fp_sqr_comba48(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_SQR64
+void fp_sqr_comba64(fp_int *A, fp_int *B);
+#endif
+/*extern const char *fp_s_rmap;*/
+
+
+/**
+ * Used by CyaSSL
+ */
+
+/* Types */
+ typedef fp_digit mp_digit;
+ typedef fp_word mp_word;
+ typedef fp_int mp_int;
+
+/* Constants */
+ #define MP_LT FP_LT /* less than */
+ #define MP_EQ FP_EQ /* equal to */
+ #define MP_GT FP_GT /* greater than */
+ #define MP_OKAY FP_OKAY /* ok result */
+ #define MP_NO FP_NO /* yes/no result */
+ #define MP_YES FP_YES /* yes/no result */
+
+/* Prototypes */
+int mp_init (mp_int * a);
+void mp_clear (mp_int * a);
+int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, mp_int* f);
+
+int mp_add (mp_int * a, mp_int * b, mp_int * c);
+int mp_sub (mp_int * a, mp_int * b, mp_int * c);
+
+int mp_mul (mp_int * a, mp_int * b, mp_int * c);
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
+
+int mp_cmp(mp_int *a, mp_int *b);
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+int mp_unsigned_bin_size(mp_int * a);
+int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b);
+
+#ifdef CYASSL_KEY_GEN
+int mp_set_int(fp_int *a, fp_digit b);
+int mp_gcd(fp_int *a, fp_int *b, fp_int *c);
+int mp_lcm(fp_int *a, fp_int *b, fp_int *c);
+int mp_copy(fp_int* a, fp_int* b);
+int mp_sub_d(fp_int *a, fp_digit b, fp_int *c);
+int mp_prime_is_prime(mp_int* a, int t, int* result);
+#endif /* CYASSL_KEY_GEN */
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* CTAO_CRYPT_TFM_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tls.c Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,451 @@
+/* tls.c
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "ssl.h"
+#include "cyassl_int.h"
+#include "cyassl_error.h"
+#include "ctc_hmac.h"
+
+
+
+#ifndef NO_TLS
+
+
+#ifndef min
+
+ static INLINE word32 min(word32 a, word32 b)
+ {
+ return a > b ? b : a;
+ }
+
+#endif /* min */
+
+
+/* calculate XOR for TLSv1 PRF */
+static INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha)
+{
+ word32 i;
+
+ for (i = 0; i < digLen; i++)
+ digest[i] = md5[i] ^ sha[i];
+}
+
+
+
+/* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */
+void p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen,
+ const byte* seed, word32 seedLen, int hash)
+{
+ word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ?
+ SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE;
+ word32 times = resLen / len;
+ word32 lastLen = resLen % len;
+ word32 lastTime;
+ word32 i;
+ word32 idx = 0;
+ byte previous[SHA256_DIGEST_SIZE]; /* max size */
+ byte current[SHA256_DIGEST_SIZE]; /* max size */
+
+ Hmac hmac;
+
+ if (lastLen) times += 1;
+ lastTime = times - 1;
+
+ HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256,
+ secret, secLen);
+ HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */
+ HmacFinal(&hmac, previous); /* A1 */
+
+ for (i = 0; i < times; i++) {
+ HmacUpdate(&hmac, previous, len);
+ HmacUpdate(&hmac, seed, seedLen);
+ HmacFinal(&hmac, current);
+
+ if ( (i == lastTime) && lastLen)
+ XMEMCPY(&result[idx], current, lastLen);
+ else {
+ XMEMCPY(&result[idx], current, len);
+ idx += len;
+ HmacUpdate(&hmac, previous, len);
+ HmacFinal(&hmac, previous);
+ }
+ }
+}
+
+
+
+/* compute TLSv1 PRF (pseudo random function using HMAC) */
+static void PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen,
+ const byte* label, word32 labLen, const byte* seed, word32 seedLen,
+ int useSha256)
+{
+ word32 half = (secLen + 1) / 2;
+
+ byte md5_half[MAX_PRF_HALF]; /* half is real size */
+ byte sha_half[MAX_PRF_HALF]; /* half is real size */
+ byte labelSeed[MAX_PRF_LABSEED]; /* labLen + seedLen is real size */
+ byte md5_result[MAX_PRF_DIG]; /* digLen is real size */
+ byte sha_result[MAX_PRF_DIG]; /* digLen is real size */
+
+ if (half > MAX_PRF_HALF)
+ return;
+ if (labLen + seedLen > MAX_PRF_LABSEED)
+ return;
+ if (digLen > MAX_PRF_DIG)
+ return;
+
+ XMEMCPY(md5_half, secret, half);
+ XMEMCPY(sha_half, secret + half - secLen % 2, half);
+
+ XMEMCPY(labelSeed, label, labLen);
+ XMEMCPY(labelSeed + labLen, seed, seedLen);
+
+ if (useSha256) {
+ p_hash(digest, digLen, secret, secLen, labelSeed, labLen + seedLen,
+ sha256_mac);
+ return;
+ }
+
+ p_hash(md5_result, digLen, md5_half, half, labelSeed, labLen + seedLen,
+ md5_mac);
+ p_hash(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen,
+ sha_mac);
+ get_xor(digest, digLen, md5_result, sha_result);
+}
+
+
+void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+ const byte* side;
+ byte handshake_hash[FINISHED_SZ];
+
+ Md5Final(&ssl->hashMd5, handshake_hash);
+ ShaFinal(&ssl->hashSha, &handshake_hash[MD5_DIGEST_SIZE]);
+
+ if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
+ side = tls_client;
+ else
+ side = tls_server;
+
+ PRF(hashes->md5, TLS_FINISHED_SZ, ssl->arrays.masterSecret, SECRET_LEN,
+ side, FINISHED_LABEL_SZ, handshake_hash, FINISHED_SZ,
+ IsAtLeastTLSv1_2(ssl));
+}
+
+
+ProtocolVersion MakeTLSv1(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = TLSv1_MINOR;
+
+ return pv;
+}
+
+
+ProtocolVersion MakeTLSv1_1(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = TLSv1_1_MINOR;
+
+ return pv;
+}
+
+
+ProtocolVersion MakeTLSv1_2(void)
+{
+ ProtocolVersion pv;
+ pv.major = SSLv3_MAJOR;
+ pv.minor = TLSv1_2_MINOR;
+
+ return pv;
+}
+
+
+static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
+static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion";
+
+
+int DeriveTlsKeys(SSL* ssl)
+{
+ int length = 2 * ssl->specs.hash_size +
+ 2 * ssl->specs.key_size +
+ 2 * ssl->specs.iv_size;
+ byte seed[SEED_LEN];
+ byte key_data[MAX_PRF_DIG];
+
+ XMEMCPY(seed, ssl->arrays.serverRandom, RAN_LEN);
+ XMEMCPY(&seed[RAN_LEN], ssl->arrays.clientRandom, RAN_LEN);
+
+ PRF(key_data, length, ssl->arrays.masterSecret, SECRET_LEN, key_label,
+ KEY_LABEL_SZ, seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
+
+ return StoreKeys(ssl, key_data);
+}
+
+
+int MakeTlsMasterSecret(SSL* ssl)
+{
+ byte seed[SEED_LEN];
+
+ XMEMCPY(seed, ssl->arrays.clientRandom, RAN_LEN);
+ XMEMCPY(&seed[RAN_LEN], ssl->arrays.serverRandom, RAN_LEN);
+
+ PRF(ssl->arrays.masterSecret, SECRET_LEN,
+ ssl->arrays.preMasterSecret, ssl->arrays.preMasterSz,
+ master_label, MASTER_LABEL_SZ,
+ seed, SEED_LEN, IsAtLeastTLSv1_2(ssl));
+
+#ifdef SHOW_SECRETS
+ {
+ int i;
+ printf("master secret: ");
+ for (i = 0; i < SECRET_LEN; i++)
+ printf("%02x", ssl->arrays.masterSecret[i]);
+ printf("\n");
+ }
+#endif
+
+ return DeriveTlsKeys(ssl);
+}
+
+
+/*** next for static INLINE s copied from cyassl_int.c ***/
+
+/* convert 16 bit integer to opaque */
+static void INLINE c16toa(word16 u16, byte* c)
+{
+ c[0] = (u16 >> 8) & 0xff;
+ c[1] = u16 & 0xff;
+}
+
+
+/* convert 32 bit integer to opaque */
+static INLINE void c32toa(word32 u32, byte* c)
+{
+ c[0] = (u32 >> 24) & 0xff;
+ c[1] = (u32 >> 16) & 0xff;
+ c[2] = (u32 >> 8) & 0xff;
+ c[3] = u32 & 0xff;
+}
+
+
+static INLINE word32 GetSEQIncrement(SSL* ssl, int verify)
+{
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls) {
+ if (verify)
+ return ssl->keys.dtls_peer_sequence_number; /* explicit from peer */
+ else
+ return ssl->keys.dtls_sequence_number - 1; /* already incremented */
+ }
+#endif
+ if (verify)
+ return ssl->keys.peer_sequence_number++;
+ else
+ return ssl->keys.sequence_number++;
+}
+
+
+#ifdef CYASSL_DTLS
+
+static INLINE word32 GetEpoch(SSL* ssl, int verify)
+{
+ if (verify)
+ return ssl->keys.dtls_peer_epoch;
+ else
+ return ssl->keys.dtls_epoch;
+}
+
+#endif /* CYASSL_DTLS */
+
+
+static INLINE const byte* GetMacSecret(SSL* ssl, int verify)
+{
+ if ( (ssl->options.side == CLIENT_END && !verify) ||
+ (ssl->options.side == SERVER_END && verify) )
+ return ssl->keys.client_write_MAC_secret;
+ else
+ return ssl->keys.server_write_MAC_secret;
+}
+
+/*** end copy ***/
+
+
+/* TLS type HAMC */
+void TLS_hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz,
+ int content, int verify)
+{
+ Hmac hmac;
+ byte seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ byte length[LENGTH_SZ];
+ byte inner[ENUM_LEN + VERSION_SZ + LENGTH_SZ]; /* type + version +len */
+ int type;
+
+ c16toa((word16)sz, length);
+#ifdef CYASSL_DTLS
+ if (ssl->options.dtls)
+ c16toa(GetEpoch(ssl, verify), seq);
+#endif
+ c32toa(GetSEQIncrement(ssl, verify), &seq[sizeof(word32)]);
+
+ if (ssl->specs.mac_algorithm == md5_mac)
+ type = MD5;
+ else
+ type = SHA;
+ HmacSetKey(&hmac, type, GetMacSecret(ssl, verify), ssl->specs.hash_size);
+
+ HmacUpdate(&hmac, seq, SEQ_SZ); /* seq_num */
+ inner[0] = content; /* type */
+ inner[ENUM_LEN] = ssl->version.major;
+ inner[ENUM_LEN + ENUM_LEN] = ssl->version.minor; /* version */
+ XMEMCPY(&inner[ENUM_LEN + VERSION_SZ], length, LENGTH_SZ); /* length */
+ HmacUpdate(&hmac, inner, sizeof(inner));
+ HmacUpdate(&hmac, buffer, sz); /* content */
+ HmacFinal(&hmac, digest);
+}
+
+
+#ifndef NO_CYASSL_CLIENT
+
+ SSL_METHOD* TLSv1_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1());
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_1_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1_1());
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_2_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1_2());
+ return method;
+ }
+
+
+ /* TODO: add downgrade */
+ SSL_METHOD* SSLv23_client_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method)
+ InitSSL_Method(method, MakeTLSv1());
+ return method;
+ }
+
+
+#endif /* NO_CYASSL_CLIENT */
+
+
+
+#ifndef NO_CYASSL_SERVER
+
+ SSL_METHOD* TLSv1_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_1_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1_1());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ SSL_METHOD* TLSv1_2_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1_2());
+ method->side = SERVER_END;
+ }
+ return method;
+ }
+
+
+ SSL_METHOD *SSLv23_server_method(void)
+ {
+ SSL_METHOD* method = (SSL_METHOD*) XMALLOC(sizeof(SSL_METHOD), 0,
+ DYNAMIC_TYPE_METHOD);
+ if (method) {
+ InitSSL_Method(method, MakeTLSv1());
+ method->side = SERVER_END;
+ method->downgrade = 1;
+ }
+ return method;
+ }
+
+
+
+#endif /* NO_CYASSL_SERVER */
+
+#else /* NO_TLS */
+
+/* catch CyaSSL programming errors */
+void BuildTlsFinished(SSL* ssl, Hashes* hashes, const byte* sender)
+{
+
+}
+
+
+int DeriveTlsKeys(SSL* ssl)
+{
+ return -1;
+}
+
+
+int MakeTlsMasterSecret(SSL* ssl)
+{
+ return -1;
+}
+
+#endif /* NO_TLS */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/types.h Sat Feb 05 01:09:17 2011 +0000
@@ -0,0 +1,191 @@
+/* types.h
+ *
+ * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
+ *
+ * This file is part of CyaSSL.
+ *
+ * CyaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CyaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#ifndef CTAO_CRYPT_TYPES_H
+#define CTAO_CRYPT_TYPES_H
+
+#include "os_settings.h"
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+#if defined(WORDS_BIGENDIAN) || (defined(__MWERKS__) && !defined(__INTEL__))
+ #define BIG_ENDIAN_ORDER
+#endif
+
+#ifndef BIG_ENDIAN_ORDER
+ #define LITTLE_ENDIAN_ORDER
+#endif
+
+#ifndef CYASSL_TYPES
+ typedef unsigned char byte;
+ typedef unsigned short word16;
+ typedef unsigned int word32;
+#endif
+
+#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define WORD64_AVAILABLE
+ #define W64LIT(x) x##ui64
+ typedef unsigned __int64 word64;
+#elif SIZEOF_LONG == 8
+ #define WORD64_AVAILABLE
+ #define W64LIT(x) x##LL
+ typedef unsigned long word64;
+#elif SIZEOF_LONG_LONG == 8
+ #define WORD64_AVAILABLE
+ #define W64LIT(x) x##LL
+ typedef unsigned long long word64;
+#else
+ #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as
+ mp_digit, no 64 bit type so make mp_digit 16 bit */
+#endif
+
+
+/* These platforms have 64-bit CPU registers. */
+#if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \
+ defined(__mips64) || defined(__x86_64__))
+ typedef word64 word;
+#else
+ typedef word32 word;
+ #ifdef WORD64_AVAILABLE
+ #define CTAOCRYPT_SLOW_WORD64
+ #endif
+#endif
+
+
+enum {
+ WORD_SIZE = sizeof(word),
+ BIT_SIZE = 8,
+ WORD_BITS = WORD_SIZE * BIT_SIZE
+};
+
+
+/* use inlining if compiler allows */
+#ifndef INLINE
+#ifndef NO_INLINE
+ #ifdef _MSC_VER
+ #define INLINE __inline
+ #elif defined(__GNUC__)
+ #define INLINE inline
+ #elif defined(THREADX)
+ #define INLINE _Inline
+ #else
+ #define INLINE
+ #endif
+#else
+ #define INLINE
+#endif
+#endif
+
+
+/* set up rotate style */
+#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define INTEL_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__MWERKS__) && TARGET_CPU_PPC
+ #define PPC_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__GNUC__) && defined(__i386__)
+ /* GCC does peephole optimizations which should result in using rotate
+ instructions */
+ #define FAST_ROTATE
+#endif
+
+
+/* Micrium will use Visual Studio for compilation but not the Win32 API */
+#if defined(_WIN32) && !defined(MICRIUM)
+ #define USE_WINDOWS_API
+#endif
+
+
+/* idea to add global alloc override by Moisés Guimarães */
+/* default to libc stuff */
+/* XREALLOC is used once in mormal math lib, not in fast math lib */
+/* XFREE on some embeded systems doesn't like free(0) so test */
+#ifdef XMALLOC_USER
+ /* prototypes for user heap override functions */
+ #include <stddef.h> /* for size_t */
+ extern void *XMALLOC(size_t n, void* heap, int type);
+ extern void *XREALLOC(void *p, size_t n, void* heap, int type);
+ extern void XFREE(void *p, void* heap, int type);
+#elif !defined(MICRIUM_MALLOC)
+ /* defaults to C runtime if user doesn't override and not Micrium */
+ #include <stdlib.h>
+ #define XMALLOC(s, h, t) malloc((s))
+ #define XFREE(p, h, t) {void* xp = (p); if((xp)) free((xp));}
+ #define XREALLOC(p, n, h, t) realloc((p), (n))
+#endif
+
+#ifndef STRING_USER
+ #include <string.h>
+ #define XMEMCPY(d,s,l) memcpy((d),(s),(l))
+ #define XMEMSET(b,c,l) memset((b),(c),(l))
+ #define XMEMCMP(s1,s2,n) memcmp((s1),(s2),(n))
+ #define XMEMMOVE(d,s,l) memmove((d),(s),(l))
+
+ #define XSTRLEN(s1) strlen((s1))
+ #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
+ /* strstr and strncmp only used by CyaSSL proper, not required for
+ CTaoCrypt only */
+ #define XSTRSTR(s1,s2) strstr((s1),(s2))
+ #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n))
+#endif
+
+
+/* memory allocation types for user hints */
+enum {
+ DYNAMIC_TYPE_CA = 1,
+ DYNAMIC_TYPE_CERT = 2,
+ DYNAMIC_TYPE_KEY = 3,
+ DYNAMIC_TYPE_FILE = 4,
+ DYNAMIC_TYPE_ISSUER_CN = 5,
+ DYNAMIC_TYPE_PUBLIC_KEY = 6,
+ DYNAMIC_TYPE_SIGNER = 7,
+ DYNAMIC_TYPE_NONE = 8,
+ DYNAMIC_TYPE_BIGINT = 9,
+ DYNAMIC_TYPE_RSA = 10,
+ DYNAMIC_TYPE_METHOD = 11,
+ DYNAMIC_TYPE_OUT_BUFFER = 12,
+ DYNAMIC_TYPE_IN_BUFFER = 13,
+ DYNAMIC_TYPE_INFO = 14,
+ DYNAMIC_TYPE_DH = 15,
+ DYNAMIC_TYPE_DOMAIN = 16,
+ DYNAMIC_TYPE_SSL = 17,
+ DYNAMIC_TYPE_CTX = 18,
+ DYNAMIC_TYPE_WRITEV = 19,
+ DYNAMIC_TYPE_OPENSSL = 20
+};
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* CTAO_CRYPT_TYPES_H */
+