Procházet zdrojové kódy

Merge remote-tracking branch 'origin/ssl'

Conflicts:
	Makefile
balbekova před 7 roky
rodič
revize
efc3428808
100 změnil soubory, kde provedl 33791 přidání a 30 odebrání
  1. 5 0
      .gdbinit_bt6702_service
  2. 5 0
      .gdbinit_bt6702_service~
  3. 14 0
      .gitignore~
  4. 1 1
      Makefile
  5. 44 0
      iap/Modules/attributes.h
  6. 877 0
      iap/Modules/rtc.c
  7. 478 0
      iap/Modules/rtc.h
  8. 1 1
      modules/Ethernet/lwipopts.h
  9. 1241 8
      modules/HTTP_Server/http_server.c
  10. 37 0
      modules/HTTP_Server/http_server.h
  11. 9 0
      modules/Makefile
  12. 2 2
      modules/startup/stm32_flash.ld
  13. binární
      output/BT_6702xx.bin
  14. binární
      output/stm32bt6702.bin
  15. 6 0
      peripheral_modules/inc/rtc.h
  16. 16 16
      peripheral_modules/src/rng.c
  17. 14 1
      peripheral_modules/src/rtc.c
  18. 108 1
      projects/iar/bt-670x.ewp
  19. 10 0
      stm32/system/syscalls/syscalls.c
  20. 38 0
      thirdparty/PolarSSL/CMakeLists.txt
  21. 441 0
      thirdparty/PolarSSL/ChangeLog
  22. 3 0
      thirdparty/PolarSSL/DartConfiguration.tcl
  23. 339 0
      thirdparty/PolarSSL/LICENSE
  24. 44 0
      thirdparty/PolarSSL/Makefile
  25. 40 0
      thirdparty/PolarSSL/README
  26. 32 0
      thirdparty/PolarSSL/contrib/indent.sh
  27. 37 0
      thirdparty/PolarSSL/doxygen/input/doc_encdec.h
  28. 20 0
      thirdparty/PolarSSL/doxygen/input/doc_hashing.h
  29. 80 0
      thirdparty/PolarSSL/doxygen/input/doc_mainpage.h
  30. 18 0
      thirdparty/PolarSSL/doxygen/input/doc_rng.h
  31. 32 0
      thirdparty/PolarSSL/doxygen/input/doc_ssltls.h
  32. 26 0
      thirdparty/PolarSSL/doxygen/input/doc_tcpip.h
  33. 21 0
      thirdparty/PolarSSL/doxygen/input/doc_x509.h
  34. 1575 0
      thirdparty/PolarSSL/doxygen/polarssl.doxyfile
  35. 5 0
      thirdparty/PolarSSL/include/CMakeLists.txt
  36. 174 0
      thirdparty/PolarSSL/include/polarssl/aes.h
  37. 80 0
      thirdparty/PolarSSL/include/polarssl/arc4.h
  38. 87 0
      thirdparty/PolarSSL/include/polarssl/base64.h
  39. 592 0
      thirdparty/PolarSSL/include/polarssl/bignum.h
  40. 738 0
      thirdparty/PolarSSL/include/polarssl/bn_mul.h
  41. 174 0
      thirdparty/PolarSSL/include/polarssl/camellia.h
  42. 47 0
      thirdparty/PolarSSL/include/polarssl/certs.h
  43. 420 0
      thirdparty/PolarSSL/include/polarssl/cipher.h
  44. 92 0
      thirdparty/PolarSSL/include/polarssl/cipher_wrap.h
  45. 628 0
      thirdparty/PolarSSL/include/polarssl/config.h
  46. 91 0
      thirdparty/PolarSSL/include/polarssl/debug.h
  47. 235 0
      thirdparty/PolarSSL/include/polarssl/des.h
  48. 151 0
      thirdparty/PolarSSL/include/polarssl/dhm.h
  49. 93 0
      thirdparty/PolarSSL/include/polarssl/error.h
  50. 67 0
      thirdparty/PolarSSL/include/polarssl/havege.h
  51. 356 0
      thirdparty/PolarSSL/include/polarssl/md.h
  52. 152 0
      thirdparty/PolarSSL/include/polarssl/md2.h
  53. 151 0
      thirdparty/PolarSSL/include/polarssl/md4.h
  54. 153 0
      thirdparty/PolarSSL/include/polarssl/md5.h
  55. 65 0
      thirdparty/PolarSSL/include/polarssl/md_wrap.h
  56. 159 0
      thirdparty/PolarSSL/include/polarssl/net.h
  57. 136 0
      thirdparty/PolarSSL/include/polarssl/openssl.h
  58. 100 0
      thirdparty/PolarSSL/include/polarssl/padlock.h
  59. 100 0
      thirdparty/PolarSSL/include/polarssl/pem.h
  60. 127 0
      thirdparty/PolarSSL/include/polarssl/pkcs11.h
  61. 372 0
      thirdparty/PolarSSL/include/polarssl/rsa.h
  62. 151 0
      thirdparty/PolarSSL/include/polarssl/sha1.h
  63. 159 0
      thirdparty/PolarSSL/include/polarssl/sha2.h
  64. 167 0
      thirdparty/PolarSSL/include/polarssl/sha4.h
  65. 683 0
      thirdparty/PolarSSL/include/polarssl/ssl.h
  66. 75 0
      thirdparty/PolarSSL/include/polarssl/timing.h
  67. 81 0
      thirdparty/PolarSSL/include/polarssl/version.h
  68. 777 0
      thirdparty/PolarSSL/include/polarssl/x509.h
  69. 111 0
      thirdparty/PolarSSL/include/polarssl/xtea.h
  70. 52 0
      thirdparty/PolarSSL/library/CMakeLists.txt
  71. 69 0
      thirdparty/PolarSSL/library/Makefile
  72. 1822 0
      thirdparty/PolarSSL/library/aes.c
  73. 173 0
      thirdparty/PolarSSL/library/arc4.c
  74. 258 0
      thirdparty/PolarSSL/library/base64.c
  75. 2097 0
      thirdparty/PolarSSL/library/bignum.c
  76. 1040 0
      thirdparty/PolarSSL/library/camellia.c
  77. 196 0
      thirdparty/PolarSSL/library/certs.c
  78. 536 0
      thirdparty/PolarSSL/library/cipher.c
  79. 552 0
      thirdparty/PolarSSL/library/cipher_wrap.c
  80. 238 0
      thirdparty/PolarSSL/library/debug.c
  81. 1255 0
      thirdparty/PolarSSL/library/des.c
  82. 290 0
      thirdparty/PolarSSL/library/dhm.c
  83. 418 0
      thirdparty/PolarSSL/library/error.c
  84. 217 0
      thirdparty/PolarSSL/library/havege.c
  85. 302 0
      thirdparty/PolarSSL/library/md.c
  86. 369 0
      thirdparty/PolarSSL/library/md2.c
  87. 465 0
      thirdparty/PolarSSL/library/md4.c
  88. 685 0
      thirdparty/PolarSSL/library/md5.c
  89. 715 0
      thirdparty/PolarSSL/library/md_wrap.c
  90. 385 0
      thirdparty/PolarSSL/library/net.c
  91. 162 0
      thirdparty/PolarSSL/library/padlock.c
  92. 350 0
      thirdparty/PolarSSL/library/pem.c
  93. 238 0
      thirdparty/PolarSSL/library/pkcs11.c
  94. 1206 0
      thirdparty/PolarSSL/library/rsa.c
  95. 726 0
      thirdparty/PolarSSL/library/sha1.c
  96. 710 0
      thirdparty/PolarSSL/library/sha2.c
  97. 765 0
      thirdparty/PolarSSL/library/sha4.c
  98. 828 0
      thirdparty/PolarSSL/library/ssl_cli.c
  99. 1029 0
      thirdparty/PolarSSL/library/ssl_srv.c
  100. 2280 0
      thirdparty/PolarSSL/library/ssl_tls.c

+ 5 - 0
.gdbinit_bt6702_service

@@ -0,0 +1,5 @@
+target remote localhost:3333
+file build/bt6702_service/stm32bt6702service/stm32bt6702service.elf
+load
+break Reset_Handler
+

+ 5 - 0
.gdbinit_bt6702_service~

@@ -0,0 +1,5 @@
+target remote localhost:3333
+file build/bt6702/stm32bt6702/stm32bt6702.elf
+load
+break Reset_Handler
+

+ 14 - 0
.gitignore~

@@ -0,0 +1,14 @@
+*.ewd
+*.eww
+*.ewt
+*.dep
+*.tmp
+
+/projects/iar/Debug/
+/projects/iar/settings/
+
+# Web
+/web_interface/node_modules
+/web_interface/dist/wui
+/web_interface/dist/upload
+/web_interface/*.sublime-workspace

+ 1 - 1
Makefile

@@ -1,4 +1,4 @@
-TARGETS = projects/gcc/tools iap modules service_hw
+TARGETS = projects/gcc/tools modules #service_hw iap 
 BUILDDIR = build
 
 .PHONY: all config $(TARGETS) tools distclean

+ 44 - 0
iap/Modules/attributes.h

@@ -0,0 +1,44 @@
+/**
+ *  Attributes for different compilers
+ * 
+ *	@author 	Tilen Majerle
+ *	@email		tilen@majerle.eu
+ *	@website	http://stm32f4-discovery.com
+ *	@version 	v1.0
+ *	@ide		Keil uVision 5
+ *	@license	GNU GPL v3
+ *	
+ * |----------------------------------------------------------------------
+ * | Copyright (C) Tilen Majerle, 2014
+ * | 
+ * | This program 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 3 of the License, or
+ * | any later version.
+ * |  
+ * | This program 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, see <http://www.gnu.org/licenses/>.
+ * |----------------------------------------------------------------------
+ *
+ * Different compilers uses different special keywords for functions/variables. etc.
+ * For this purpose that file has been made. On one place to all possible attributes used in my libs.
+ */
+#ifndef TM_ATTRIBUTES_H
+#define TM_ATTRIBUTES_H
+
+/* Check for GNUC */
+#if defined (__GNUC__)
+	#ifndef __weak		
+		#define __weak   	__attribute__((weak))
+	#endif	/* Weak attribute */
+	#ifndef __packed	
+		#define __packed 	__attribute__((__packed__))
+	#endif	/* Packed attribute */
+#endif
+
+#endif

+ 877 - 0
iap/Modules/rtc.c

@@ -0,0 +1,877 @@
+/**	
+ * |----------------------------------------------------------------------
+ * | Copyright (C) Tilen Majerle, 2014
+ * | 
+ * | This program 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 3 of the License, or
+ * | any later version.
+ * |  
+ * | This program 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, see <http://www.gnu.org/licenses/>.
+ * |----------------------------------------------------------------------
+ */
+#include "rtc.h"
+
+/* Private macros */
+/* Internal status registers for RTC */
+#define RTC_STATUS_REG      			RTC_BKP_DR19 /* Status Register */
+#define RTC_STATUS_INIT_OK  			0x1234       /* RTC initialised */
+#define RTC_STATUS_TIME_OK  			0x4321       /* RTC time OK */
+#define	RTC_STATUS_ZERO					0x0000
+
+/* Internal RTC defines */
+#define TM_RTC_LEAP_YEAR(year) 			((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
+#define TM_RTC_DAYS_IN_YEAR(x)			TM_RTC_LEAP_YEAR(x) ? 366 : 365
+#define TM_RTC_OFFSET_YEAR				1970
+#define TM_RTC_SECONDS_PER_DAY			86400
+#define TM_RTC_SECONDS_PER_HOUR			3600
+#define TM_RTC_SECONDS_PER_MINUTE		60
+#define TM_RTC_BCD2BIN(x)				((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))
+#define TM_RTC_CHAR2NUM(x)				((x) - '0')
+#define TM_RTC_CHARISNUM(x)				((x) >= '0' && (x) <= '9')
+
+/* Internal functions */
+void TM_RTC_Config(TM_RTC_ClockSource_t source);
+/* Default RTC status */
+uint32_t TM_RTC_Status = RTC_STATUS_ZERO;
+/* RTC declarations */
+RTC_TimeTypeDef RTC_TimeStruct;
+RTC_InitTypeDef RTC_InitStruct;
+RTC_DateTypeDef RTC_DateStruct;
+NVIC_InitTypeDef NVIC_InitStruct;
+EXTI_InitTypeDef EXTI_InitStruct;
+
+RTC_InitTypeDef   RTC_InitStructure;
+RTC_TimeTypeDef   RTC_TimeStructure;
+RTC_DateTypeDef   RTC_DateStructure;
+
+#define RTC_CLOCK_SOURCE_LSE           /* LSE used as RTC source clock */
+#define FIRST_DATA          0x32F2
+#define RTC_BKP_DR_NUMBER   0x14
+
+__IO uint32_t uwAsynchPrediv = 0;
+__IO uint32_t uwSynchPrediv = 0;
+__IO uint32_t uwTimeDisplay = 0;
+
+uint32_t uwErrorIndex = 0;
+uint32_t uwIndex = 0;
+
+uint32_t aBKPDataReg[RTC_BKP_DR_NUMBER] =
+  {
+    RTC_BKP_DR0, RTC_BKP_DR1, RTC_BKP_DR2, 
+    RTC_BKP_DR3, RTC_BKP_DR4, RTC_BKP_DR5,
+    RTC_BKP_DR6, RTC_BKP_DR7, RTC_BKP_DR8, 
+    RTC_BKP_DR9, RTC_BKP_DR10, RTC_BKP_DR11, 
+    RTC_BKP_DR12, RTC_BKP_DR13, RTC_BKP_DR14, 
+    RTC_BKP_DR15, RTC_BKP_DR16, RTC_BKP_DR17, 
+    RTC_BKP_DR18,  RTC_BKP_DR19
+  };
+
+/* Days in a month */
+uint8_t TM_RTC_Months[2][12] = {
+	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},	/* Not leap year */
+	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}	/* Leap year */
+};
+
+/**
+  * @brief  Writes data to all Backup data registers.
+  * @param  FirstBackupData: data to write to first backup data register.
+  * @retval None
+  */
+static void WriteToBackupReg(uint16_t FirstBackupData)
+{
+  uint32_t index = 0;
+
+  for (index = 0; index < RTC_BKP_DR_NUMBER; index++)
+  {
+    RTC_WriteBackupRegister(aBKPDataReg[index], FirstBackupData + (index * 0x5A));
+  }
+
+}
+
+uint32_t TM_RTC_Init(TM_RTC_ClockSource_t source) 
+{
+  uint32_t status;
+  uint8_t stat = 1;
+  TM_RTC_t datatime;
+	
+  /* Enable PWR peripheral clock */
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
+
+  /* Allow access to BKP Domain */
+  PWR_BackupAccessCmd(ENABLE);
+	
+  /* Get RTC status */
+  status = RTC_ReadBackupRegister(RTC_STATUS_REG);
+	
+  if (status == RTC_STATUS_TIME_OK) 
+  {
+    TM_RTC_Status = RTC_STATUS_TIME_OK;
+		
+    /* Start internal clock if we choose internal clock */
+    if (source == TM_RTC_ClockSource_Internal)
+      TM_RTC_Config(TM_RTC_ClockSource_Internal);
+
+    /* Wait for RTC APB registers synchronisation (needed after start-up from Reset) */
+    RTC_WaitForSynchro();
+		
+    /* Clear interrupt flags */
+    RTC_ClearITPendingBit(RTC_IT_WUT);
+    EXTI->PR = 0x00400000;
+		
+    /* Get date and time */
+    TM_RTC_GetDateTime(&datatime, TM_RTC_Format_BIN);
+  } 
+  else if (status == RTC_STATUS_INIT_OK) 
+  {
+    TM_RTC_Status = RTC_STATUS_INIT_OK;
+		
+    /* Start internal clock if we choose internal clock */
+    if (source == TM_RTC_ClockSource_Internal)
+      TM_RTC_Config(TM_RTC_ClockSource_Internal);
+
+    /* Wait for RTC APB registers synchronisation (needed after start-up from Reset) */
+    RTC_WaitForSynchro();
+		
+    /* Clear interrupt flags */
+    RTC_ClearITPendingBit(RTC_IT_WUT);
+    EXTI->PR = 0x00400000;
+		
+    /* Get date and time */
+    //TM_RTC_GetDateTime(&datatime, TM_RTC_Format_BIN);
+  } 
+  else 
+  {
+    TM_RTC_Status = RTC_STATUS_ZERO;
+    /* Return status = 0 -> RTC Never initialized before */
+    stat = RTC_STATUS_ZERO;
+    /* Config RTC */
+	TM_RTC_Config(source);
+		
+    /* Set date and time */
+    datatime.date = 1;
+    datatime.day = 1;
+    datatime.month = 1;
+    datatime.year = 0;
+    datatime.hours = 0;
+    datatime.minutes = 0;
+    datatime.seconds = 0;
+
+    /* Set date and time */
+    TM_RTC_SetDateTime(&datatime, TM_RTC_Format_BIN);
+		
+    /* Initialized OK */
+    TM_RTC_Status = RTC_STATUS_INIT_OK;
+  }
+  /* If first time initialized */
+  if (stat == RTC_STATUS_ZERO) 
+	return 0;
+  
+  return TM_RTC_Status;  
+
+}
+
+void TM_RTC_SetDataTimeUnix(uint32_t unixTime)
+{
+  TM_RTC_t data;
+  
+  TM_RTC_GetDateTimeFromUnix(&data, unixTime);
+  TM_RTC_SetDateTime(&data, TM_RTC_Format_BIN);
+}
+
+/**
+  * @brief  Кореектировака времени.
+  * @param  Часовой пояс
+  * @retval 
+  */
+void TM_RTC_Correction(float utc)
+{
+  TM_RTC_t data;
+  TM_RTC_t newData;
+  int      utcSec;
+  uint32_t unixTime;
+  
+  /* Получаем текущее время */
+  TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
+  
+  /* Рассчитываем поправку */
+  utcSec = (int)(3600.0*utc);
+  unixTime = data.unix + utcSec;
+  
+  /* Устанавливаем новое время */
+  TM_RTC_GetDateTimeFromUnix(&newData, unixTime);
+  TM_RTC_SetDateTime(&newData, TM_RTC_Format_BIN);
+}
+
+TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) {
+	TM_RTC_t tmp;
+	
+	/* Check date and time validation */
+	if (format == TM_RTC_Format_BCD) {
+		tmp.date = TM_RTC_BCD2BIN(data->date);
+		tmp.month = TM_RTC_BCD2BIN(data->month);
+		tmp.year = TM_RTC_BCD2BIN(data->year);
+		tmp.hours = TM_RTC_BCD2BIN(data->hours);
+		tmp.minutes = TM_RTC_BCD2BIN(data->minutes);
+		tmp.seconds = TM_RTC_BCD2BIN(data->seconds);
+		tmp.day = TM_RTC_BCD2BIN(data->day);
+	} else {
+		tmp.date = data->date;
+		tmp.month = data->month;
+		tmp.year = data->year;
+		tmp.hours = data->hours;
+		tmp.minutes = data->minutes;
+		tmp.seconds = data->seconds;
+		tmp.day = data->day;
+	}
+	
+	/* Check year and month */
+	if (
+		tmp.year > 99 || 
+		tmp.month == 0 || 
+		tmp.month > 12 ||
+		tmp.date == 0 ||
+		tmp.date > TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + tmp.year) ? 1 : 0][tmp.month - 1] ||
+		tmp.hours > 23 ||
+		tmp.minutes > 59 ||
+		tmp.seconds > 59 ||
+		tmp.day == 0 ||
+		tmp.day > 7
+	) {
+		/* Invalid date */
+		return TM_RTC_Result_Error; 
+	}
+	
+	/* Fill time */
+	RTC_TimeStruct.RTC_Hours = data->hours;
+	RTC_TimeStruct.RTC_Minutes = data->minutes;
+	RTC_TimeStruct.RTC_Seconds = data->seconds;
+	/* Fill date */
+	RTC_DateStruct.RTC_Date = data->date;
+	RTC_DateStruct.RTC_Month = data->month;
+	RTC_DateStruct.RTC_Year = data->year;
+	RTC_DateStruct.RTC_WeekDay = data->day;
+	
+	/* Set the RTC time base to 1s and hours format to 24h */
+	RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
+	RTC_InitStruct.RTC_AsynchPrediv = RTC_ASYNC_PREDIV;
+	RTC_InitStruct.RTC_SynchPrediv = RTC_SYNC_PREDIV;
+	RTC_Init(&RTC_InitStruct);
+
+	/* Set time */
+	if (format == TM_RTC_Format_BCD) {
+		RTC_SetTime(RTC_Format_BCD, &RTC_TimeStruct);
+	} else {
+		RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
+	}
+	
+	/* Set date */
+	if (format == TM_RTC_Format_BCD) {
+		RTC_SetDate(RTC_Format_BCD, &RTC_DateStruct);
+	} else {
+		RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
+	}	
+	
+	if (TM_RTC_Status != RTC_STATUS_ZERO) {
+		/* Write backup registers */
+		RTC_WriteBackupRegister(RTC_STATUS_REG, RTC_STATUS_TIME_OK);
+	}
+	
+	/* Return OK */
+	return TM_RTC_Result_Ok;
+}
+
+TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str) {
+	TM_RTC_t tmp;
+	uint8_t i = 0;
+	
+	/* Get date */
+	tmp.date = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get month */
+	tmp.month = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get year */
+	tmp.year = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get day in a week */
+	tmp.day = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.day = tmp.day * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get hours */
+	tmp.hours = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get minutes */
+	tmp.minutes = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Get seconds */
+	tmp.seconds = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.seconds = tmp.seconds * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	/* Return status from set date time function */
+	return TM_RTC_SetDateTime(&tmp, TM_RTC_Format_BIN);
+}
+
+void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) {
+	uint32_t unix;
+
+	/* Get time */
+	if (format == TM_RTC_Format_BIN) {
+		RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
+	} else {
+		RTC_GetTime(RTC_Format_BCD, &RTC_TimeStruct);
+	}
+	
+	/* Format hours */
+	data->hours = RTC_TimeStruct.RTC_Hours;
+	data->minutes = RTC_TimeStruct.RTC_Minutes;
+	data->seconds = RTC_TimeStruct.RTC_Seconds;
+	
+	/* Get subseconds */
+	data->subseconds = RTC->SSR;
+	
+	/* Get date */
+	if (format == TM_RTC_Format_BIN) {
+		RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
+	} else {
+		RTC_GetDate(RTC_Format_BCD, &RTC_DateStruct);
+	}
+	
+	/* Format date */
+	data->year = RTC_DateStruct.RTC_Year;
+	data->month = RTC_DateStruct.RTC_Month;
+	data->date = RTC_DateStruct.RTC_Date;
+	data->day = RTC_DateStruct.RTC_WeekDay;
+	
+	/* Calculate unix offset */
+	unix = TM_RTC_GetUnixTimeStamp(data);
+	data->unix = unix;
+}
+
+uint8_t TM_RTC_GetDaysInMonth(uint8_t month, uint8_t year) {
+	/* Check input data */
+	if (
+		month == 0 ||
+		month > 12
+	) {
+		/* Error */
+		return 0;
+	}
+	
+	/* Return days in month */
+	return TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + year) ? 1 : 0][month - 1];
+}
+
+uint16_t TM_RTC_GetDaysInYear(uint8_t year) {
+	/* Return days in year */
+	return TM_RTC_DAYS_IN_YEAR(2000 + year);
+}
+
+void TM_RTC_Config(TM_RTC_ClockSource_t source) {
+	if (source == TM_RTC_ClockSource_Internal) {
+		/* Enable the LSI OSC */
+		RCC_LSICmd(ENABLE);
+
+		/* Wait till LSI is ready */
+		while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
+
+		/* Select the RTC Clock Source */
+		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
+	} else if (source == TM_RTC_ClockSource_External) {
+		/* Enable the LSE OSC */
+		RCC_LSEConfig(RCC_LSE_ON);
+
+		/* Wait till LSE is ready */ 
+		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
+
+		/* Select the RTC Clock Source */
+		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
+	}
+	
+	/* Enable the RTC Clock */
+	RCC_RTCCLKCmd(ENABLE);
+	
+	/* Wait for register synchronization */
+	RTC_WaitForSynchro();
+
+	/* Write status */
+	RTC_WriteBackupRegister(RTC_STATUS_REG, RTC_STATUS_INIT_OK);
+}
+
+void TM_RTC_Interrupts(TM_RTC_Int_t int_value) {
+	uint32_t int_val;
+	
+	/* Clear pending bit */
+	EXTI->PR = 0x00400000;
+	
+	/* Disable wakeup interrupt */
+	RTC_WakeUpCmd(DISABLE);
+	
+	/* Disable RTC interrupt flag */
+	RTC_ITConfig(RTC_IT_WUT, DISABLE);
+	
+	/* NVIC init for RTC */
+	NVIC_InitStruct.NVIC_IRQChannel = RTC_WKUP_IRQn;
+	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelSubPriority = RTC_WAKEUP_SUBPRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE;
+	NVIC_Init(&NVIC_InitStruct); 
+	
+	/* RTC connected to EXTI_Line22 */
+	EXTI_InitStruct.EXTI_Line = EXTI_Line22;
+	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
+	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
+	EXTI_InitStruct.EXTI_LineCmd = DISABLE;
+	EXTI_Init(&EXTI_InitStruct);
+	
+	if (int_value != TM_RTC_Int_Disable) {
+		/* Enable NVIC */
+		NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
+		NVIC_Init(&NVIC_InitStruct); 
+		/* Enable EXT1 interrupt */
+		EXTI_InitStruct.EXTI_LineCmd = ENABLE;
+		EXTI_Init(&EXTI_InitStruct);
+
+		/* First disable wake up command */
+		RTC_WakeUpCmd(DISABLE);
+
+		if (int_value == TM_RTC_Int_60s) {
+			int_val = 0x3BFFF; 		/* 60 seconds = 60 * 4096 / 1 = 245760 */
+		} else if (int_value == TM_RTC_Int_30s) {
+			int_val = 0x1DFFF;		/* 30 seconds */
+		} else if (int_value == TM_RTC_Int_15s) {
+			int_val = 0xEFFF;		/* 15 seconds */
+		} else if (int_value == TM_RTC_Int_10s) {
+			int_val = 0x9FFF;		/* 10 seconds */
+		} else if (int_value == TM_RTC_Int_5s) {
+			int_val = 0x4FFF;		/* 5 seconds */
+		} else if (int_value == TM_RTC_Int_2s) {
+			int_val = 0x1FFF;		/* 2 seconds */
+		} else if (int_value == TM_RTC_Int_1s) {
+			int_val = 0x0FFF;		/* 1 second */
+		} else if (int_value == TM_RTC_Int_500ms) {
+			int_val = 0x7FF;		/* 500 ms */
+		} else if (int_value == TM_RTC_Int_250ms) {
+			int_val = 0x3FF;		/* 250 ms */
+		} else if (int_value == TM_RTC_Int_125ms) {
+			int_val = 0x1FF;		/* 125 ms */
+		}		
+
+		/* Clock divided by 8, 32768 / 8 = 4096 */
+		/* 4096 ticks for 1second interrupt */
+		RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div8);
+		
+		/* Set RTC wakeup counter */
+		RTC_SetWakeUpCounter(int_val);
+		/* Enable wakeup interrupt */
+		RTC_ITConfig(RTC_IT_WUT, ENABLE);
+		/* Enable wakeup command */
+		RTC_WakeUpCmd(ENABLE);
+	}
+}
+
+uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data) {
+	uint32_t days = 0, seconds = 0;
+	uint16_t i;
+	uint16_t year = (uint16_t) (data->year + 2000);
+	/* Year is below offset year */
+	if (year < TM_RTC_OFFSET_YEAR) {
+		return 0;
+	}
+	/* Days in back years */
+	for (i = TM_RTC_OFFSET_YEAR; i < year; i++) {
+		days += TM_RTC_DAYS_IN_YEAR(i);
+	}
+	/* Days in current year */
+	for (i = 1; i < data->month; i++) {
+		days += TM_RTC_Months[TM_RTC_LEAP_YEAR(year)][i - 1];
+	}
+	/* Day starts with 1 */
+	days += data->date - 1;
+	seconds = days * TM_RTC_SECONDS_PER_DAY;
+	seconds += data->hours * TM_RTC_SECONDS_PER_HOUR;
+	seconds += data->minutes * TM_RTC_SECONDS_PER_MINUTE;
+	seconds += data->seconds;
+	
+	/* seconds = days * 86400; */
+	return seconds;
+}
+
+void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix) {
+	uint16_t year;
+	
+	/* Store unix time to unix in struct */
+	data->unix = unix;
+	/* Get seconds from unix */
+	data->seconds = unix % 60;
+	/* Go to minutes */
+	unix /= 60;
+	/* Get minutes */
+	data->minutes = unix % 60;
+	/* Go to hours */
+	unix /= 60;
+	/* Get hours */
+	data->hours = unix % 24;
+	/* Go to days */
+	unix /= 24;
+	
+	/* Get week day */
+	/* Monday is day one */
+	data->day = (unix + 3) % 7 + 1;
+
+	/* Get year */
+	year = 1970;
+	while (1) {
+		if (TM_RTC_LEAP_YEAR(year)) {
+			if (unix >= 366) {
+				unix -= 366;
+			} else {
+				break;
+			}
+		} else if (unix >= 365) {
+			unix -= 365;
+		} else {
+			break;
+		}
+		year++;
+	}
+	/* Get year in xx format */
+	data->year = (uint8_t) (year - 2000);
+	/* Get month */
+	for (data->month = 0; data->month < 12; data->month++) {
+		if (TM_RTC_LEAP_YEAR(year) && unix >= (uint32_t)TM_RTC_Months[1][data->month]) {
+			unix -= TM_RTC_Months[1][data->month];
+		} else if (unix >= (uint32_t)TM_RTC_Months[0][data->month]) {
+			unix -= TM_RTC_Months[0][data->month];
+		} else {
+			break;
+		}
+	}
+	/* Get month */
+	/* Month starts with 1 */
+	data->month++;
+	/* Get date */
+	/* Date starts with 1 */
+	data->date = unix + 1;
+}
+
+void TM_RTC_SetAlarm(TM_RTC_Alarm_t Alarm, TM_RTC_AlarmTime_t* DataTime, TM_RTC_Format_t format) {
+	RTC_AlarmTypeDef RTC_AlarmStruct;
+	
+	/* Disable alarm first */
+	TM_RTC_DisableAlarm(Alarm);
+	
+	/* Set RTC alarm settings */
+	/* Set alarm time */
+	RTC_AlarmStruct.RTC_AlarmTime.RTC_Hours = DataTime->hours;
+	RTC_AlarmStruct.RTC_AlarmTime.RTC_Minutes = DataTime->minutes;
+	RTC_AlarmStruct.RTC_AlarmTime.RTC_Seconds = DataTime->seconds;
+	RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;
+	
+	/* Alarm type is every week the same day in a week */
+	if (DataTime->alarmtype == TM_RTC_AlarmType_DayInWeek) {
+		/* Alarm trigger every week the same day in a week */
+		RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay;
+		
+		/* Week day can be between 1 and 7 */
+		if (DataTime->day == 0) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 1;
+		} else if (DataTime->day > 7) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 7;
+		} else {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = DataTime->day;
+		}
+	} else { /* Alarm type is every month the same day */
+		/* Alarm trigger every month the same day in a month */
+		RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
+	
+		/* Month day can be between 1 and 31 */
+		if (DataTime->day == 0) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 1;
+		} else if (DataTime->day > 31) {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = 31;
+		} else {
+			RTC_AlarmStruct.RTC_AlarmDateWeekDay = DataTime->day;
+		}
+	}
+
+	switch (Alarm) {
+		case TM_RTC_Alarm_A:		
+			/* Configure the RTC Alarm A */
+			RTC_SetAlarm(format, RTC_Alarm_A, &RTC_AlarmStruct);
+		
+			/* Enable Alarm A */
+			RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
+			
+			/* Enable Alarm A interrupt */
+			RTC_ITConfig(RTC_IT_ALRA, ENABLE);
+		
+			/* Clear Alarm A pending bit */
+			RTC_ClearFlag(RTC_IT_ALRA);
+			break;
+		case TM_RTC_Alarm_B:
+			/* Configure the RTC Alarm B */
+			RTC_SetAlarm(format, RTC_Alarm_B, &RTC_AlarmStruct);
+		
+			/* Enable Alarm B */
+			RTC_AlarmCmd(RTC_Alarm_B, ENABLE);
+		
+			/* Enable Alarm B interrupt */
+			RTC_ITConfig(RTC_IT_ALRB, ENABLE);
+		
+			/* Clear Alarm B pending bit */
+			RTC_ClearFlag(RTC_IT_ALRB);
+			break;
+		default:
+			break;
+	}
+}
+
+void TM_RTC_DisableAlarm(TM_RTC_Alarm_t Alarm) {
+	switch (Alarm) {
+		case TM_RTC_Alarm_A:
+			/* Disable Alarm A */
+			RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
+			
+			/* Disable Alarm A interrupt */
+			RTC_ITConfig(RTC_IT_ALRA, DISABLE);
+		
+			/* Clear Alarm A pending bit */
+			RTC_ClearFlag(RTC_IT_ALRA);
+			break;
+		case TM_RTC_Alarm_B:
+			/* Disable Alarm B */
+			RTC_AlarmCmd(RTC_Alarm_B, DISABLE);
+		
+			/* Disable Alarm B interrupt */
+			RTC_ITConfig(RTC_IT_ALRB, DISABLE);
+		
+			/* Clear Alarm B pending bit */
+			RTC_ClearFlag(RTC_IT_ALRB);
+			break;
+		default:
+			break;
+	}
+	
+	/* Clear RTC Alarm pending bit */
+	EXTI->PR = 0x00020000;
+	
+	/* Configure EXTI 17 as interrupt */
+	EXTI_InitStruct.EXTI_Line = EXTI_Line17;
+	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
+	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
+	EXTI_InitStruct.EXTI_LineCmd = ENABLE;
+	
+	/* Initialite Alarm EXTI interrupt */
+	EXTI_Init(&EXTI_InitStruct);
+
+	/* Configure the RTC Alarm Interrupt */
+	NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn;
+	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelSubPriority = RTC_ALARM_SUBPRIORITY;
+	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
+	
+	/* Initialize RTC Alarm Interrupt */
+	NVIC_Init(&NVIC_InitStruct);
+}
+
+void TM_RTC_WriteBackupRegister(uint8_t location, uint32_t value) {
+	/* Check input, 0 to 18 registers are allowed */
+	if (location > 18) {
+		return;
+	}
+	
+	/* Write data to backup register */
+	*(uint32_t *)((&RTC->BKP0R) + 4 * location) = value;
+}
+
+uint32_t TM_RTC_ReadBackupRegister(uint8_t location){
+	/* Check input, 0 to 18 registers are allowed */
+	if (location > 18) {
+		return 0;
+	}
+	
+	/* Read data from backup register */
+	return *(uint32_t *)((&RTC->BKP0R) + 4 * location);
+}
+
+/* Callbacks */
+__weak void TM_RTC_RequestHandler(void) {
+	/* If user needs this function, then they should be defined separatelly in your project */
+}
+
+__weak void TM_RTC_AlarmAHandler(void) {
+	/* If user needs this function, then they should be defined separatelly in your project */
+}
+
+__weak void TM_RTC_AlarmBHandler(void) {
+	/* If user needs this function, then they should be defined separatelly in your project */
+}
+
+/* Private RTC IRQ handlers */
+void RTC_WKUP_IRQHandler(void) {
+	/* Check for RTC interrupt */
+	if (RTC_GetITStatus(RTC_IT_WUT) != RESET) {
+		/* Clear interrupt flags */
+		RTC_ClearITPendingBit(RTC_IT_WUT);
+		
+		/* Call user function */
+		TM_RTC_RequestHandler();
+	}
+	
+	/* Clear EXTI line 22 bit */
+	EXTI->PR = 0x00400000;
+}
+
+void RTC_Alarm_IRQHandler(void) {
+	/* RTC Alarm A check */
+	if (RTC_GetITStatus(RTC_IT_ALRA) != RESET) {
+		/* Clear RTC Alarm A interrupt flag */
+		RTC_ClearITPendingBit(RTC_IT_ALRA);
+		
+		/* Call user function for Alarm A */
+		TM_RTC_AlarmAHandler();
+	}
+	
+	/* RTC Alarm B check */
+	if (RTC_GetITStatus(RTC_IT_ALRB) != RESET) {
+		/* Clear RTC Alarm A interrupt flag */
+		RTC_ClearITPendingBit(RTC_IT_ALRB);
+		
+		/* Call user function for Alarm B */
+		TM_RTC_AlarmBHandler();
+	}
+	
+	/* Clear EXTI line 17 bit */
+	EXTI->PR = 0x00020000;
+}
+
+/**
+  * @brief  Установливает время срабатывания профилактики сульфатации для отладки
+  * @retval 
+  */
+void RTC_SetDebugProfTime(void)
+{
+  TM_RTC_t currentTime;
+  uint32_t unixTime;
+  
+  TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
+  
+  unixTime = TM_RTC_GetUnixTimeStamp(&currentTime);
+    
+  unixTime += 30;
+  
+  TM_RTC_WriteBackupRegister(RTC_BKP_DR0, unixTime);
+}
+
+/**
+  * @brief  Установливает время срабатывания профилактики сульфатации
+  */
+void RTC_SetProfTime(char *str)
+{
+  TM_RTC_t tmp;
+  uint32_t unixTime;
+  uint8_t i = 0;
+	
+  /* Get date */
+  tmp.date = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+	
+  /* Get month */
+  tmp.month = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  //i++;
+  i+=3;
+  
+  /* Get year */
+  tmp.year = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+  i++;
+	
+  /* Get hours */
+  tmp.hours = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+	
+  /* Get minutes */
+  tmp.minutes = 0;
+  while (TM_RTC_CHARISNUM(*(str + i))) {
+	tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
+	i++;
+  }
+  i++;
+	
+  /* Get seconds */
+  tmp.seconds = 0;
+	
+  /* Устанавливаем +1 для профилактики */
+  tmp.year += 1;
+  unixTime = TM_RTC_GetUnixTimeStamp(&tmp);  
+  TM_RTC_WriteBackupRegister(RTC_BKP_DR0, unixTime);
+}
+
+/**
+  * @brief  
+  * @retval 
+  */
+uint32_t RTC_GetUnixTime(void)
+{
+  TM_RTC_t currentTime;
+  
+  TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
+  return TM_RTC_GetUnixTimeStamp(&currentTime);
+}
+

+ 478 - 0
iap/Modules/rtc.h

@@ -0,0 +1,478 @@
+/**
+ * @author  Tilen Majerle
+ * @email   tilen@majerle.eu
+ * @website http://stm32f4-discovery.com
+ * @link    http://stm32f4-discovery.com/2014/07/library-19-use-internal-rtc-on-stm32f4xx-devices/
+ * @version 1.7.1
+ * @ide     Keil uVision
+ * @license GNU GPL v3
+ * @brief   Internal RTC library for STM32F4xx devices
+ *	
+@verbatim
+   ----------------------------------------------------------------------
+    Copyright (C) Tilen Majerle, 2015
+    
+    This program 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 3 of the License, or
+    any later version.
+     
+    This program 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, see <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------
+@endverbatim
+ */
+#ifndef TM_RTC_H
+#define TM_RTC_H 171
+
+/* C++ detection */
+#ifdef __cplusplus
+extern C {
+#endif
+
+/**
+ * @addtogroup TM_STM32F4xx_Libraries
+ * @{
+ */
+
+/**
+ * @defgroup TM_RTC
+ * @brief    RTC Library for STM32F4xx devices - http://stm32f4-discovery.com/2014/07/library-19-use-internal-rtc-on-stm32f4xx-devices/
+ * @{
+ *
+ * \par Features
+ *
+@verbatim
+- Support Internal or external clock source
+  - PC14 and PC15 pins are used for external crystal oscillator
+  - STM32F4/429 Discovery does not have RTC crystal onboard. Check board's manual on how to set it up
+- Support wakeup interrupt
+- Support to set 2 internal alarms to trigger interrupts
+  - They can also wake up STM32F4 from any low power mode
+- Get seconds from 01.01.1970 00:00:00
+- Get readable time from seconds from 01.01.1970 00:00:00
+- Support to save/get data in binary or BCD format
+- Support for read/write data to/from RTC backup registers
+- Support for subsecond
+- Support to write data in string format
+- Date and time are checked before saved for valid input data
+- Get days in month and year
+@endverbatim
+ *
+ * \par Pinout for RTC external 32768Hz crystal
+ *
+@verbatim
+ STM32F4XX  Oscillator   Description
+	
+ PC14       OSC1         Oscillator terminal 1
+ PC15       OSC2         Oscillator terminal 2
+@endverbatim
+ *
+ * \par Changelog
+ *
+@verbatim
+ Version 1.7.1
+   - March 25, 2015
+   - Fixed issue with RTC wakeup interrupts
+
+ Version 1.7
+   - March 15, 2015
+   - Added support for read/write data to/from RTC backup registers
+
+ Version 1.6
+   - February 17, 2015
+   - Created typedef TM_RTC_t from TM_RTC_Time_t
+
+ Version 1.5
+   - December 21, 2014
+   - Added 2 new functions:
+      TM_RTC_GetDaysInMonth: returns number of days in specific month and year
+      TM_RTC_GetDaysInYear: returns number of days in specific year
+
+ Version 1.4
+   - December 21, 2014
+   - TM_RTC_SetDateTime now checks for valid input data before save
+   - Added function TM_RTC_SetDateTimeString which allows you to set your
+      date and time using string format
+
+ Version 1.3
+   - December 03, 2014
+   - Fixed bug when reading month in december was set to 0
+
+ Version 1.2
+   - October 27, 2014
+   - Added support to read subseconds from time
+   - This can be used for stopwatch
+
+ Version 1.1
+   - October 20, 2014
+   - Added support for Alarm set
+
+ Version 1.0.2
+   - September 24, 2014
+   - TM_RTC_RequestHandler function has now "__weak" attribute to prevent errors,
+      if function is not implemented by user
+
+ Version 1.0.1
+   - September 01, 2014
+   - Date to unix convert bug fix
+
+ Version 1.0
+   - First release
+@endverbatim
+ *
+ * \par Dependencies
+ *
+@verbatim
+ - STM32F4xx
+ - STM32F4xx RCC
+ - STM32F4xx RTC
+ - STM32F4xx PWR
+ - STM32F4xx EXTI
+ - MISC
+ - defines.h
+ - attributes.h
+@endverbatim
+ */
+#include "stm32f4xx.h"
+#include "attributes.h"
+
+/**
+ * @defgroup TM_RTC_Macros
+ * @brief    Library defines
+ *
+ * All these settings can be overwritten in defines.h file if necessary
+ *
+ * @{
+ */
+
+/* RTC clock is: f_clk = RTCCLK(LSI or LSE) / ((RTC_SYNC_PREDIV + 1) * (RTC_ASYNC_PREDIV + 1)) */
+/* Sync pre division for clock */
+#ifndef RTC_SYNC_PREDIV
+#define RTC_SYNC_PREDIV					0x3FF
+#endif
+/* Async pre division for clock */
+#ifndef RTC_ASYNC_PREDIV
+#define RTC_ASYNC_PREDIV				0x1F
+#endif
+/* NVIC global Priority set */
+#ifndef RTC_PRIORITY
+#define RTC_PRIORITY					0x04
+#endif
+/* Sub priority for wakeup trigger */
+#ifndef RTC_WAKEUP_SUBPRIORITY
+#define RTC_WAKEUP_SUBPRIORITY			0x00
+#endif
+/* Sub priority for alarm trigger */
+#ifndef RTC_ALARM_SUBPRIORITY
+#define RTC_ALARM_SUBPRIORITY			0x01
+#endif
+
+ /**
+ * @}
+ */
+ 
+/**
+ * @defgroup TM_RTC_Typedefs
+ * @brief    Library Typedefs
+ * @{
+ */
+
+/**
+ * @brief  RTC Struct for date/time
+ */
+typedef struct {
+	uint8_t seconds;     /*!< Seconds parameter, from 00 to 59 */
+	uint16_t subseconds; /*!< Subsecond downcounter. When it reaches zero, it's reload value is the same as
+                                 @ref RTC_SYNC_PREDIV, so in our case 0x3FF = 1023, 1024 steps in one second */
+	uint8_t minutes;     /*!< Minutes parameter, from 00 to 59 */
+	uint8_t hours;       /*!< Hours parameter, 24Hour mode, 00 to 23 */
+	uint8_t day;         /*!< Day in a week, from 1 to 7 */
+	uint8_t date;        /*!< Date in a month, 1 to 31 */
+	uint8_t month;       /*!< Month in a year, 1 to 12 */
+	uint8_t year;        /*!< Year parameter, 00 to 99, 00 is 2000 and 99 is 2099 */
+	uint32_t unix;       /*!< Seconds from 01.01.1970 00:00:00 */
+} TM_RTC_t;
+
+/**
+ * @brief  Backward compatibility for RTC time
+ */
+typedef TM_RTC_t TM_RTC_Time_t;
+
+/**
+ * @brief RTC Result enumeration
+ */
+typedef enum {
+	TM_RTC_Result_Ok,   /*!< Everything OK */
+	TM_RTC_Result_Error /*!< An error occurred */
+} TM_RTC_Result_t;
+
+/**
+ * @brief RTC date and time format
+ */
+typedef enum {
+	TM_RTC_Format_BIN = 0x00, /*!< RTC data in binary format */
+	TM_RTC_Format_BCD         /*!< RTC data in binary-coded decimal format */
+} TM_RTC_Format_t;
+
+/**
+ * @brief  RTC Interrupt enumeration
+ */
+typedef enum {
+	TM_RTC_Int_Disable = 0x00, /*!< Disable RTC wakeup interrupts */
+	TM_RTC_Int_60s,            /*!< RTC Wakeup interrupt every 60 seconds */
+	TM_RTC_Int_30s,            /*!< RTC Wakeup interrupt every 30 seconds */
+	TM_RTC_Int_15s,            /*!< RTC Wakeup interrupt every 15 seconds */
+	TM_RTC_Int_10s,            /*!< RTC Wakeup interrupt every 10 seconds */
+	TM_RTC_Int_5s,             /*!< RTC Wakeup interrupt every 5 seconds */
+	TM_RTC_Int_2s,             /*!< RTC Wakeup interrupt every 2 seconds */
+	TM_RTC_Int_1s,             /*!< RTC Wakeup interrupt every 1 seconds */
+	TM_RTC_Int_500ms,          /*!< RTC Wakeup interrupt every 500 milliseconds */
+	TM_RTC_Int_250ms,          /*!< RTC Wakeup interrupt every 250 milliseconds */
+	TM_RTC_Int_125ms           /*!< RTC Wakeup interrupt every 125 milliseconds */
+} TM_RTC_Int_t;
+
+/**
+ * @brief  Select RTC clock source
+ * @note   Internal clock is not accurate and should not be used in production
+ */
+typedef enum {
+	TM_RTC_ClockSource_Internal = 0x00, /*!< Use internal clock source for RTC (LSI oscillator) */
+	TM_RTC_ClockSource_External         /*!< Use external clock source for RTC (LSE oscillator) */
+} TM_RTC_ClockSource_t;
+
+/**
+ * @brief  RTC Alarm type
+ */
+typedef enum {
+	TM_RTC_AlarmType_DayInWeek, /*!< Trigger alarm every day in a week, days from 1 to 7 (Monday to Sunday) */
+	TM_RTC_AlarmType_DayInMonth /*!< Trigger alarm every month */
+} TM_RTC_AlarmType_t;
+
+/**
+ * @brief  Alarm identifier you will use for Alarm functions
+ */
+typedef enum {
+	TM_RTC_Alarm_A = 0x00, /*!< Work with alarm A */
+	TM_RTC_Alarm_B         /*!< Work with alarm B */
+} TM_RTC_Alarm_t;
+
+/**
+ * @brief  RTC structure for alarm time
+ */
+typedef struct {
+	TM_RTC_AlarmType_t alarmtype; /*!< Alarm type setting. @ref TM_RTC_AlarmType_t for more info */
+	uint8_t seconds;              /*!< Alarm seconds value */
+	uint8_t minutes;              /*!< Alarm minutes value */
+	uint8_t hours;                /*!< Alarm hours value */
+	uint8_t day;                  /*!< Alarm day value. If you select trigger for alarm every week, then this parameter has value between
+                                          1 and 7, representing days in a week, Monday to Sunday
+                                          If you select trigger for alarm every month, then this parameter has value between
+                                          1 - 31, representing days in a month. */
+} TM_RTC_AlarmTime_t;
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup TM_RTC_Functions
+ * @brief    Library Functions
+ * @{
+ */
+
+
+void TM_RTC_SetDataTimeUnix(uint32_t unixTime);
+
+/**
+  * @brief  Кореектировака времени.
+  */
+void TM_RTC_Correction(float utc);
+
+/**
+ * @brief  Initializes RTC and starts counting
+ * @param  source. RTC Clock source @ref TM_RTC_ClockSource_t to be used for RTC
+ * @note   Internal clock source is not so accurate
+ * @note   If you reset your MCU and RTC still has power, it will count independent of MCU status
+ * @retval Returns RTC status.
+ *            - 1: RTC has already been initialized and time is set
+ *            - 0: RTC was now initialized first time. Now you can set your first clock
+ */
+uint32_t TM_RTC_Init(TM_RTC_ClockSource_t source);
+
+/**
+ * @brief  Get number of seconds from date and time since 01.01.1970 00:00:00
+ * @param  *data: Pointer to @ref TM_RTC_t data structure
+ * @retval Calculated seconds from date and time since 01.01.1970 00:00:00
+ */
+uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data);
+
+/**
+ * @brief  Get formatted time from seconds till 01.01.1970 00:00:00
+ *         It fills struct with valid data
+ * @note   Valid if year is greater or equal (>=) than 2000
+ * @param  *data: Pointer to @ref TM_RTC_Time_t struct to store formatted data in
+ * @param  unix: Seconds from 01.01.1970 00:00:00 to calculate user friendly time
+ * @retval None
+ */
+void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix);
+
+/**
+ * @brief  Select RTC wakeup interrupts interval
+ * @note   This function can also be used to disable interrupt
+ * @param  int_value: Look for @ref TM_RTC_Int_t for valid inputs
+ * @retval None
+ */
+void TM_RTC_Interrupts(TM_RTC_Int_t int_value);
+
+/**
+ * @brief  Set date and time to internal RTC registers
+ * @param  *data: Pointer to filled @ref TM_RTC_t structure with date and time
+ * @param  format: Format of your structure. This parameter can be a value of @ref TM_RTC_Format_t enumeration
+ * @retval RTC datetime status @ref TM_RTC_Result_t:
+ *            - @ref TM_RTC_Result_Ok: Date and Time set OK
+ *            - @ref TM_RTC_Result_Error: Date and time is wrong
+ */
+TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data, TM_RTC_Format_t format);
+
+/**
+ * @brief  Set date and time using string formatted date time
+ * @note   Valid string format is: <b>dd.mm.YY.x;HH:ii:ss</b>
+ *            - <b>dd</b>: date, 2 digits, decimal
+ *            - <b>mm</b>: month, 2 digits, decimal
+ *            - <b>YY</b>: year, last 2 digits, decimal
+ *            - <b>x</b>: day in a week: 1 digit, 1 = Monday, 7 = Sunday
+ *            - <b>HH</b>: hours, 24-hour mode, 2 digits, decimal
+ *            - <b>ii</b>: minutes, 2 digits, decimal
+ *            - <b>ss</b>: seconds, 2 digits, decimal
+ * @param  *str: Pointer to string with datetime format
+ * @retval RTC datetime status @ref TM_RTC_Result_t:
+ *            - @ref TM_RTC_Result_Ok: Date and Time set OK
+ *            - @ref TM_RTC_Result_Error: Date and time is wrong
+ */
+TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str);
+
+/**
+ * @brief  Get date and time from internal RTC registers
+ * @param  *data: Pointer to @ref TM_RTC_t structure to save data to
+ * @param  format: Format of your structure. This parameter can be a value of @ref TM_RTC_Format_t enumeration
+ * @retval None
+ */
+void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format);
+
+/**
+ * @brief  Get number of days in month
+ * @note   This function also detects if it is leap year and returns different number for February
+ * @param  month: Month number in year, valid numbers are 1 - 12 
+ * @param  year: Year number where you want to get days in month, last 2 digits
+ * @retval Number of days in specific month and year
+ */
+uint8_t TM_RTC_GetDaysInMonth(uint8_t month, uint8_t year);
+
+/**
+ * @brief  Get number of days in specific year
+ * @note   This function also detects if it is leap year
+ * @param  year: Year number where you want to get days in month, last 2 digits
+ * @retval Number of days in year
+ */
+uint16_t TM_RTC_GetDaysInYear(uint8_t year);
+
+/**
+ * @brief  Write RTC backup register value.
+ *            This method allows you to write 32bit value from backup register 0 - 18.
+ * @note   RTC has 20 backup registers where you can store data which will be available all the time RTC is running and has power.
+ *
+ * @note   My library uses register 19 to store info about RTC settings and is not available for USER to store data there.
+ *
+ * @note   RTC HAS to be initialized first before you can use this method.
+ * @param  location: RTC backup register location. 0 to 18 are valid
+ * @param  value: 32-bit long value to be stored in RTC backup register
+ * @retval Value at specific RTC backup register location
+ */
+void TM_RTC_WriteBackupRegister(uint8_t location, uint32_t value);
+
+/**
+ * @brief  Read RTC backup register value.
+ *            This method allows you to read 32bit value from backup register 0 - 18.
+ * @note   RTC has 20 backup registers where you can store data which will be available all the time RTC is running and has power.
+ *
+ * @note   My library uses register 19 to store info about RTC settings and is not available for USER to store data there.
+ *
+ * @note   RTC HAS to be initialized first before you can use this method.
+ * @param  location: RTC backup register location. 0 to 18 are valid
+ * @retval Value at specific RTC backup register location
+ */
+uint32_t TM_RTC_ReadBackupRegister(uint8_t location);
+
+/**
+ * @brief  Enables alarm A or alarm B
+ * @param  Alarm: Specify which alarm to set. This parameter can be a value of @ref TM_RTC_Alarm_t enumeration
+ * @param  *AlarmTime: Pointer to @ref TM_RTC_AlarmTime_t structure to get data from.
+ * @param  format: RTC date and time format. This parameter can be a value of @ref TM_RTC_Format_t enumeration.
+ * @retval None
+ */
+void TM_RTC_SetAlarm(TM_RTC_Alarm_t Alarm, TM_RTC_AlarmTime_t* AlarmTime, TM_RTC_Format_t format);
+
+/**
+ * @brief  Disables specific alarm
+ * @param  Alarm: Select which alarm you want to disable. This parameter can be a value of @ref TM_RTC_Alarm_t enumeration
+ * @retval None
+ */
+void TM_RTC_DisableAlarm(TM_RTC_Alarm_t Alarm);
+
+/**
+ * @brief  RTC Wakeup handler function. Called when wakeup interrupt is triggered
+ * @note   Called from my RTC library
+ * @param  None
+ * @retval None
+ * @note   With __weak parameter to prevent link errors if not defined by user
+ */
+void TM_RTC_RequestHandler(void);
+
+/**
+ * @brief  RTC Alarm A handler function. Called when interrupt is triggered for alarm A
+ * @note   Called from my RTC library
+ * @param  None
+ * @retval None
+ * @note   With __weak parameter to prevent link errors if not defined by user
+ */
+void TM_RTC_AlarmAHandler(void);
+
+/**
+ * @brief  RTC Alarm B handler function. Called when interrupt is triggered for alarm B.
+ * @note   Called from my RTC library
+ * @param  None
+ * @retval None
+ * @note   With __weak parameter to prevent link errors if not defined by user
+ */
+void TM_RTC_AlarmBHandler(void);
+
+/**
+  * @brief  У�тановливает врем� �рабатывани� профилактики �ульфатации дл� отладки
+  * @retval 
+  */
+void RTC_SetDebugProfTime(void);
+
+/**
+  * @brief  Óñòàíîâëèâàåò âðåìÿ ñðàáàòûâàíèÿ ïðîôèëàêòèêè ñóëüôàòàöèè
+  */
+void RTC_SetProfTime(char *date);
+
+/**
+  * @brief  
+  * @retval 
+  */
+uint32_t RTC_GetUnixTime(void);
+
+/* C++ detection */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 1 - 1
modules/Ethernet/lwipopts.h

@@ -209,7 +209,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
 /**
  * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
  */
-#define LWIP_SOCKET                     0
+#define LWIP_SOCKET                     1
 
 /*
    -----------------------------------

+ 1241 - 8
modules/HTTP_Server/http_server.c

@@ -589,10 +589,10 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb,  struct pbuf *p, err_t er
 			 {
 				 //DBG printf("State: Received %d bytes\r\n", (int)TotalReceived);
 
-				 strncat(&sendBuf,  ptr, receivedBufLen);
-				 strncat(&sendBuf,  " ", 1);
+				 strncat(sendBuf,  ptr, receivedBufLen);
+				 strncat(sendBuf,  " ", 1);
 				 //ВBG printf("receive %s /r/n", sendBuf);
-				 HTTP_SetSettings(sendBuf, strlen(&sendBuf));
+				 HTTP_SetSettings(sendBuf, strlen(sendBuf));
 
 				 DataFlag2=0;
 				 BrowserFlag = 0;
@@ -618,7 +618,7 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb,  struct pbuf *p, err_t er
 			   if(receivedBufLen)
 			   {
 
-				 strncat(&sendBuf,  ptr, receivedBufLen);
+				 strncat(sendBuf,  ptr, receivedBufLen);
 				 //memcpy(receiveBufTemp, ptr, receivedBufLen);
 			   }
 			 }
@@ -719,9 +719,9 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb,  struct pbuf *p, err_t er
 			 if (TotalReceived == size)
 			 {
 
-				 strncat(&sendBuf,  ptr, receivedBufLen);
-				 strncat(&sendBuf,  " ", 1);
-				 HTTP_SetInfo(sendBuf, strlen(&sendBuf));
+				 strncat(sendBuf,  ptr, receivedBufLen);
+				 strncat(sendBuf,  " ", 1);
+				 HTTP_SetInfo(sendBuf, strlen(sendBuf));
 				 DataFlag=0;
 				 BrowserFlag = 0;
 				 memset(sendBuf, 0, size);
@@ -746,7 +746,7 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb,  struct pbuf *p, err_t er
 			   if(receivedBufLen)
 			   {
 
-				 strncat(&sendBuf,  ptr, receivedBufLen);
+				 strncat(sendBuf,  ptr, receivedBufLen);
 				 //memcpy(receiveBufTemp, ptr, receivedBufLen);
 			   }
 			 }
@@ -2110,3 +2110,1236 @@ int HTTP_ChangeUserPwd(char *bufIn, char *bufOut, uint16_t lenBufIn, uint16_t *l
       return SEND_REQUIRED_YES;
   }
 }
+
+
+// -----------------------------------------------------------------------------
+//
+//
+//  SSL тесты
+//
+//
+// -----------------------------------------------------------------------------
+
+//#include "stm32f4xx.h"
+#include "rtc.h"
+
+/* PolarSSL includes */
+#include "polarssl/net.h"
+#include "polarssl/ssl.h"
+#include "polarssl/havege.h"
+#include "polarssl/certs.h"
+#include "polarssl/x509.h"
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define DEBUG_LEVEL 1  /* Set DEBUG_LEVEL if you want to enable SSL debug
+                         option, this should be set to 2, 3, 4 or 5 */
+                         
+#define HTTP_RESPONSE "<p><p>Successful connection using: %s\r\n"
+
+/* Format of dynamic web page */
+#define PAGE_START \
+"<html>\
+<head>\
+</head>\
+<BODY onLoad=\"window.setTimeout(&quot;location.href='index.html'&quot;,1000)\" bgcolor=\"#FFFFFF\" text=\"#000000\">\
+<font size=\"4\" color=\"#0000FF\"><b>STM32F407xx : SSL Server Demo not using HW Crypto :<)</font></b></i>\
+<br><br><pre>\r\nPage Hits = "
+
+#define PAGE_END \
+" \r\n</pre><br><br><hr>\
+<font size=\"3\" color=\"#808080\">All rights reserved ©2017 ROTEK\
+\r\n</font></BODY>\
+</html>"
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* SSL structures */
+rng_state rngs;
+ssl_context ssl;
+ssl_session ssn;
+x509_cert srvcert;
+rsa_context rsa;
+uint32_t nPageHits = 0;
+
+/* Private functions ---------------------------------------------------------*/
+/*
+ * Computing a "safe" DH-1024 prime can take a very
+ * long time, so a precomputed value is provided below.
+ * You may run dh_genprime to generate a new value.
+ */
+
+char *my_dhm_P = 
+  "E4004C1F94182000103D883A448B3F80" \
+  "2CE4B44A83301270002C20D0321CFD00" \
+  "11CCEF784C26A400F43DFB901BCA7538" \
+  "F2C6B176001CF5A0FD16D2C48B1D0C1C" \
+  "F6AC8E1DA6BCC3B4E1F96B0564965300" \
+  "FFA1D0B601EB2800F489AA512C4B248C" \
+  "01F76949A60BB7F00A40B1EAB64BDD48" \
+  "E8A700D60B7F1200FA8E77B0A979DABF";
+
+char *my_dhm_G = "4";
+
+/*
+ * Sorted by order of preference
+ */
+int my_ciphersuites[] =
+{
+  SSL_EDH_RSA_AES_256_SHA,
+  SSL_EDH_RSA_CAMELLIA_256_SHA,
+  SSL_EDH_RSA_AES_128_SHA,
+  SSL_EDH_RSA_CAMELLIA_128_SHA,
+  SSL_EDH_RSA_DES_168_SHA,
+  SSL_RSA_AES_256_SHA,
+  SSL_RSA_CAMELLIA_256_SHA,
+  SSL_RSA_AES_128_SHA,
+  SSL_RSA_CAMELLIA_128_SHA,
+  SSL_RSA_DES_168_SHA,
+  SSL_RSA_RC4_128_SHA,
+  SSL_RSA_RC4_128_MD5,
+  0
+};
+
+void my_debug(void *ctx, int level, const char *str)
+{
+  if(level < DEBUG_LEVEL)
+  {
+    printf("\r%s", str);  
+  }
+}
+
+/*
+ * These session callbacks use a simple chained list
+ * to store and retrieve the session information.
+ */
+ssl_session *s_list_1st = NULL;
+ssl_session *cur, *prv;
+
+static int my_get_session(ssl_context *ssl)
+{
+  time_t t = RTC_GetUnixTime(); //time(NULL);
+
+  if(ssl->resume == 0)
+    return(1);
+
+  cur = s_list_1st;
+  prv = NULL;
+
+  while(cur != NULL)
+  {
+    prv = cur;
+    cur = cur->next;
+
+    if(ssl->timeout != 0 && t - prv->start > ssl->timeout)
+      continue;
+
+    if( ssl->session->ciphersuite != prv->ciphersuite ||
+        ssl->session->length != prv->length)
+      continue;
+
+    if(memcmp( ssl->session->id, prv->id, prv->length ) != 0)
+      continue;
+
+    memcpy(ssl->session->master, prv->master, 48);
+      return(0);
+  }
+
+  return(1);
+}
+
+static int my_set_session(ssl_context *ssl)
+{
+  time_t t = RTC_GetUnixTime(); //time(NULL);
+
+  cur = s_list_1st;
+  prv = NULL;
+
+  while(cur != NULL)
+  {
+    if(ssl->timeout != 0 && t - cur->start > ssl->timeout)
+      break; /* expired, reuse this slot */
+
+    if(memcmp( ssl->session->id, cur->id, cur->length ) == 0)
+      break; /* client reconnected */
+
+    prv = cur;
+    cur = cur->next;
+  }
+
+  if(cur == NULL)
+  {
+    cur = (ssl_session *) malloc(sizeof(ssl_session));
+    if(cur == NULL)
+      return(1);
+
+    if(prv == NULL)
+      s_list_1st = cur;
+    else  prv->next  = cur;
+  }
+
+  memcpy(cur, ssl->session, sizeof(ssl_session));
+
+  return(0);
+}
+
+/**
+  * @brief  SSL Server task.
+  * @param  pvParameters not used
+  * @retval None
+  */
+void ssl_server(void *pvParameters)
+{
+    int ret, len;
+    int listen_fd;
+    int client_fd;
+    char buf[1024];
+    
+    char *ptr;
+    char CookieBuf[50];
+    char *CookiePtr = NULL;
+    char name[MAX_WEB_COOKIE_LEN];
+    char id[MAX_WEB_COOKIE_LEN];
+    uint8_t nameLen = 0, idLen = 0;
+    uint32_t DataOffset;
+    struct fs_file file = {0, 0};
+    uint32_t i;
+    
+    memset(&srvcert, 0, sizeof(x509_cert));
+    
+    // 1. Load the certificates and private RSA key 
+    //printf("\n\r Loading the server certificates and key...");
+    
+  
+    // This demonstration program uses embedded test certificates.
+    // Instead, you may want to use x509parse_crtfile() to read the
+    // server and CA certificates, as well as x509parse_keyfile().
+ 
+    ret = x509parse_crt(&srvcert, (unsigned char *) test_srv_crt, strlen(test_srv_crt));
+    if(ret != 0)
+    {
+        //printf(" failed\n  !  x509parse_crt returned %d\n\r", ret);
+        goto exit;
+    }
+    ret = x509parse_crt(&srvcert, (unsigned char *) test_ca_crt, strlen(test_ca_crt));
+    if(ret != 0)
+    {
+        //printf(" failed\n  !  x509parse_crt returned %d\n\r", ret);
+        goto exit;
+    }
+    rsa_init( &rsa, RSA_PKCS_V15, 0 );
+    ret =  x509parse_key(&rsa, (unsigned char *) test_srv_key, strlen(test_srv_key), NULL, 0);
+    if( ret != 0 )
+    {
+        //printf(" failed\n  !  x509parse_key returned %d\n\r", ret);
+        goto exit;
+    }
+    
+    // 2. Setup the listening TCP socket 
+    //printf("\n\r Bind to https port ...");
+  
+    // Bind the connection to https port : 443 
+    ret = net_bind(&listen_fd, NULL, 443); 
+    if(ret != 0)
+    {
+        //printf(" failed\n  ! net_bind returned %d\n\r", ret);
+        goto exit;
+    }
+    //printf(" ok\n\r");
+    
+    // 3. Wait until a client connects 
+    for(;;)
+    {
+        //printf("\n\r Waiting for a remote connection ...");
+        ret = net_accept(listen_fd, &client_fd, NULL);
+        if(ret != 0)
+        {
+            //printf(" failed\n  ! net_accept returned %d\n\n", ret);
+            goto exit;
+        }
+        //printf(" ok\n");
+
+        // 4. Initialize the session data 
+        //printf("\n\r Setting up the RNG and SSL data....");
+    
+        // Initialize the SSL context 
+        ret = ssl_init(&ssl);
+        if(ret != 0)
+        {
+            //printf(" failed\n  ! ssl_init returned %d\n\n", ret);
+            goto accept;
+        }
+        //printf(" ok\n");
+
+        // Set the current session as SSL server 
+        ssl_set_endpoint(&ssl, SSL_IS_SERVER);
+        // No certificate verification 
+        ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
+        // Set the random number generator callback function 
+        ssl_set_rng(&ssl, RandVal, &rngs); 
+        // Set the debug callback function 
+        //ssl_set_dbg(&ssl, my_debug, stdout);
+        // Set read and write callback functions 
+        ssl_set_bio(&ssl, net_recv, &client_fd, net_send, &client_fd);
+        // Set the session callback functions 
+        ssl_set_scb(&ssl, my_get_session, my_set_session);
+        // The list of ciphersuites to be used in this session 
+        ssl_set_ciphersuites(&ssl, my_ciphersuites);
+        // Set the session resuming flag, timeout and session context 
+        ssl_set_session(&ssl, 1, 0, &ssn);
+        memset(&ssn, 0, sizeof(ssl_session));
+        // Set the data required to verify peer certificate 
+        ssl_set_ca_chain(&ssl, srvcert.next, NULL, NULL);
+        // Set own certificate and private key 
+        ssl_set_own_cert(&ssl, &srvcert, &rsa);
+        // Set the Diffie-Hellman public P and G values 
+        ssl_set_dh_param(&ssl, my_dhm_P, my_dhm_G);
+
+        // 5. Handshake protocol 
+        //printf("\n\r Performing the SSL/TLS handshake...");
+
+        // Perform the SSL handshake protocol 
+        while((ret = ssl_handshake(&ssl)) != 0)
+        {
+            if(ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE)
+            {
+                //printf(" failed\n  ! ssl_handshake returned %d\n\n", ret);
+                goto accept;
+            }
+        }
+        //printf(" ok\n");
+
+        // 6. Read the HTTP Request 
+        //printf("\n\r <= Read from client :");
+        do
+        {
+            receivedBufLen = RECIVE_BUF_MAX_LEN - 1;
+            memset(receiveBuf, 0, RECIVE_BUF_MAX_LEN);
+
+            // Read decrypted application data 
+            ret = ssl_read(&ssl, (unsigned char*)receiveBuf, receivedBufLen);
+
+            if(ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE)
+                continue;
+
+            if(ret <= 0)
+            {
+                switch(ret)
+                {
+                case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
+                    printf("\n\r connection was closed \n");
+                break;
+
+                case POLARSSL_ERR_NET_CONN_RESET:
+                    printf("\n\r connection was reset by peer\n");
+                break;
+
+                default:
+                    //printf("\n\r ssl_read returned %d\n", ret);
+                break;
+                }
+                break;
+            }
+            receivedBufLen = ret;
+            // Display the length of read data 
+            //printf("\n\r Successfully read %d bytes from client \n\r",len);
+        }while(0);
+
+    // -------------------------------------------------------------------------
+        
+        //receivedBufLen = p->tot_len;
+        //memcpy(receiveBuf, p->payload , receivedBufLen);
+
+        receiveBuf[receivedBufLen] = '\0';
+        // printf("receive %s \r\n", receiveBuf);
+        // Get cookie "uname" value 
+        CookiePtr = strstr(receiveBuf, "uname=");
+        strncpy(CookieBuf, CookiePtr, 50);
+        //printf("********CookieBuf1= %s\r\n", CookieBuf);
+        memset(name, 0, MAX_WEB_COOKIE_LEN);
+        GetCookieValue(CookieBuf, "uname=", name, &nameLen);
+        //printf("********CookieBuf2= %s\r\n", CookieBuf);
+        //printf("********uname= %s\r\n", name);
+
+        // Get cookie "id" value 
+        CookiePtr = strstr(receiveBuf, "id=");
+        strncpy(CookieBuf, CookiePtr, 50);
+        //printf("********CookieBuf1= %s\r\n", CookieBuf);
+        memset(id, 0, MAX_WEB_COOKIE_LEN);
+        GetCookieValue(CookieBuf, "id=", id, &idLen);
+        //printf("********CookieBuf2= %s\r\n", CookieBuf);
+        //printf("********id= %s\r\n", id);
+
+
+        // Id of currently logged-in user 
+        uint8_t user_id;
+        
+        if( DataFlag == 0 && DataFlag2 == 0 ) {
+        // Level of currently logged-in user 
+        seclevel = 0xFF;
+        for (user_id = 0; user_id < MAX_WEB_USERS; user_id++) {
+            HTTP_GetUserCookie(user_id, CookieBuf, &idLen);
+            if (strncmp(id, CookieBuf, idLen) == 0 ) {
+                GetUserLevelInt(user_id, &seclevel);
+                Authenticated = true;
+                break;
+            }
+            Authenticated = false;
+            seclevel = 0xFF;
+        }
+        }
+        if (DataFlag >= 1)
+            Authenticated = true;
+        else if(DataFlag2 >= 1)
+            Authenticated = true;
+       
+        if ( Authenticated == false && sSettings.sRADIUS.Auth_enable == false)
+        {
+            HTTP_LOGIN(sendBuf, &sendBufLoadLen);
+            ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+        }
+        else if ( Authenticated == false )//&& sSettings.sRADIUS.Auth_enable == true
+        {
+            if (strncmp(receiveBuf, "GET /main.css", 13) == 0) // +
+            {
+                fs_open("/main.css", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /rotek.png", 14) == 0) // +
+            {
+                fs_open("/rotek.png", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /favicon.ico", 16) == 0) // ?
+            {
+                fs_open("/favicon.ico", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /role.js", 12) == 0)
+            {
+                fs_open("/role.js", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if ((strncmp(receiveBuf, "POST /login.cgi", 15) == 0) || (log_post_reqn > 0))
+            {
+                uint32_t i, offset = 0, req_data_received = 0;
+                
+                post_data_count = Parse_Content_Length(receiveBuf, receivedBufLen);
+			  
+                if (post_data_count < MAX_POST_REQ_LEN) 
+                {
+                    memset(post_req_data, 0, MAX_POST_REQ_LEN);
+					
+					for (i = 0; i < receivedBufLen; i++)
+					{
+						if (strncmp ((char*)(receiveBuf+i), "\r\n\r\n", 4) == 0)
+						{
+							offset = i+4;
+							break;
+						}
+					}
+
+					req_data_received = receivedBufLen - offset;
+					
+					if (offset != 0) 
+                    {
+                        if (req_data_received < post_data_count) 
+                        {
+                            snprintf(post_req_data, req_data_received, "%s", receiveBuf);
+                            post_data_count -= req_data_received;
+                        }
+                        else 
+                        {
+                            strncat(post_req_data, (char *)(receiveBuf + offset), post_data_count);
+						
+                            if (HTTP_ConfirmWebPwd(post_req_data, sendBuf, strlen(post_req_data), &sendBufLoadLen) == SEND_REQUIRED_YES) 
+                            {
+                                ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                            }
+                            else 
+                            {
+                                fs_open("/login.html", &file);
+                                ssl_sendframes(&ssl, file.data, file.len);
+                            }
+                            post_data_count = 0;
+                            log_post_reqn = 0;
+                        }
+					}
+					/* request was fragmented before "\r\n\r\n" */
+					else 
+                    {
+						log_post_reqn++;
+						/* wait max 2 requests */
+						if (log_post_reqn > 1) 
+                        {
+							/* Redirect to login page */
+							fs_open("/login.html", &file);
+                            ssl_sendframes(&ssl, file.data, file.len);
+							/* End reqest */
+							post_data_count = 0;
+							log_post_reqn = 0;
+						}
+					}
+                }
+                else 
+                {
+                    //printf("Too long POST request!\r\n");
+                    /* Ignore request */
+                    post_data_count = 0;
+                    log_post_reqn = 0;
+
+                    /* Redirect to login page */
+                    fs_open("/login.html", &file);
+                    ssl_sendframes(&ssl, file.data, file.len);
+                }
+            }
+			else if (post_data_count > 0)
+			{
+                strncat(post_req_data, receiveBuf, post_data_count);
+
+                if (HTTP_ConfirmWebPwd(post_req_data, sendBuf, strlen(post_req_data), &sendBufLoadLen) == SEND_REQUIRED_YES) 
+                {
+                    ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                }
+				else 
+                {
+					fs_open("/login.html", &file);
+                    ssl_sendframes(&ssl, file.data, file.len);
+				}
+                post_data_count = 0;
+				log_post_reqn = 0;
+			}
+            else
+            {
+                fs_open("/login.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+			}
+        }
+        else if ( Authenticated == true ) 
+        {
+            if (strncmp(receiveBuf, "GET /main.css", 13) == 0) // +
+            {
+                fs_open("/main.css", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /rotek.png", 14) == 0) // +
+            {
+                fs_open("/rotek.png", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /favicon.ico", 16) == 0) // ?                 
+            {                                                                     
+                fs_open("/favicon.ico", &file);                                     
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /main.js", 12) == 0) // +
+            {
+                fs_open("/main.js", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /role.js", 12) == 0)
+            {
+                fs_open("/role.js", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /settings.html", 18) == 0) // +
+            {
+                HTTP_UpdateUserLoginTime(user_id);
+                if (seclevel == 0)
+                {
+                    fs_open("/settings.html", &file);
+                    ssl_sendframes(&ssl, file.data, file.len);
+                }
+                else 
+                {
+                    fs_open("/index.html", &file);
+                    ssl_sendframes(&ssl, file.data, file.len);
+				}
+            }
+            else if (strncmp(receiveBuf, "GET /info.html", 14) == 0) // +
+            {
+                HTTP_UpdateUserLoginTime(user_id);
+                fs_open("/info.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /history.html", 17) == 0)
+            {
+                HTTP_UpdateUserLoginTime(user_id);
+                fs_open("/history.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /ups_history.html", 21) == 0)
+            {
+                HTTP_UpdateUserLoginTime(user_id);
+                fs_open("/ups_history.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            else if (strncmp(receiveBuf, "GET /getJson.cgi", 16) == 0) // +
+            {
+                HTTP_GetParamsPage1(sendBuf);
+                ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+            }	  
+            else if (strncmp(receiveBuf, "GET /settings.cgi", 17) == 0) // +
+            {
+                if (seclevel == 0) {
+                    SET_PAGE = SET_PAGE_PAGE2;
+                    if (HTTP_SettingsPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen) == SEND_REQUIRED_YES)
+                    {
+                        ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                    }
+                }
+            }
+            else if (strncmp(receiveBuf, "POST /settings.cgi", 18) == 0)
+            {
+                if (seclevel == 0) 
+                {
+                    DataOffset = 0;
+
+                    // POST Packet received 
+                    if (DataFlag2 == 0)
+                    {
+                        BrowserFlag = 0;
+                        TotalReceived = 0;
+                        memset(sendBuf, 0, strlen(sendBuf));
+
+                        // parse packet for Content-length field 
+                        size = Parse_Content_Length(receiveBuf, receivedBufLen);
+
+                        // parse packet for the octet-stream field 
+                        for (i = 0; i < receivedBufLen; i++)
+                        {
+                            if (strncmp ((char*)(receiveBuf+i), "managerIP", 8)==0)
+                            {
+                                DataOffset = i;
+                                break;
+                            }
+                        }     
+                        /* case of MSIE8 : we do not receive data in the POST packet*/
+                        if (DataOffset == 0)
+                        {
+                            DataFlag2++;
+                            BrowserFlag = 1;
+                            //pbuf_free(p);
+                            return;
+                        }
+                        // case of Mozilla Firefox v3.6 : we receive data in the POST packet
+                        else
+                        {
+                            //TotalReceived = receivedBufLen - (ContentLengthOffset + 4);
+                            TotalReceived = receivedBufLen - DataOffset;
+                        }
+                    }
+                    if (((DataFlag2 ==1)&&(BrowserFlag==1)) || ((DataFlag2 ==0)&&(BrowserFlag==0)))
+                    {
+                        if ((DataFlag2 ==0)&&(BrowserFlag==0))
+                        {
+                            DataFlag2++;
+                        }
+                        else if ((DataFlag2 ==1)&&(BrowserFlag==1))
+                        {
+                        // parse packet for the octet-stream field */
+                            for (i = 0; i < receivedBufLen; i++)
+                            {
+                                if (strncmp ((char*)(receiveBuf+i), "managerIP", 8)==0)
+                                {
+                                    DataOffset = i;
+                                    break;
+                                }
+                            }
+                            TotalReceived += receivedBufLen;
+                            DataFlag2++;
+                        }
+                        TotalData = 0;
+                    }
+                    // DataFlag >1 => the packet is data only  
+                    else
+                    {
+                        TotalReceived +=receivedBufLen;
+                    }
+
+                    ptr = (char*)(receiveBuf + DataOffset);
+                    receivedBufLen-= DataOffset;
+
+                    // update Total data received counter 
+                    TotalData +=receivedBufLen;
+
+                    // check if last data packet 
+                    if (TotalReceived == size)
+                    {
+                        //DBG printf("State: Received %d bytes\r\n", (int)TotalReceived);
+
+                        strncat(sendBuf,  ptr, receivedBufLen);
+                        strncat(sendBuf,  " ", 1);
+                        //ВBG printf("receive %s /r/n", sendBuf);
+                        HTTP_SetSettings(sendBuf, strlen(sendBuf));
+
+                        DataFlag2=0;
+                        BrowserFlag = 0;
+                        memset(sendBuf, 0, size);
+
+                        strcpy(sendBuf, "HTTP/1.1 200 OK\r\n");
+                        strcat(sendBuf, "\r\n\r\n");
+                        strcat(sendBuf,"<!DOCTYPE html><html lang=""><head><meta http-equiv=\"refresh\" content=\"0;url=/settings.html\"/></head></html>\r\n\r\n");
+
+                        sendBufLoadLen = strlen(sendBuf);
+                        ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                    }
+                    // not last data packet 
+                    else
+                    {
+                        // write data in flash 
+                        if(receivedBufLen)
+                        {
+                            strncat(sendBuf,  ptr, receivedBufLen);
+                            //memcpy(receiveBufTemp, ptr, receivedBufLen);
+                        }
+                    }
+                }  
+            } 
+            else if (strncmp(receiveBuf, "GET /info.cgi", 13) == 0) // +
+            {
+                if (HTTP_InfoPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen) == SEND_REQUIRED_YES)
+                {
+                    ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                }
+            }
+            else if (strncmp(receiveBuf, "POST /info.cgi", 14) == 0)
+            {
+                if (seclevel == 0) 
+                {
+                    DataOffset = 0;
+
+                    // POST Packet received 
+                    if (DataFlag == 0)
+                    {
+                        BrowserFlag = 0;
+                        TotalReceived = 0;
+                        memset(sendBuf, 0, strlen(sendBuf));
+
+                        // parse packet for Content-length field 
+                        size = Parse_Content_Length(receiveBuf, receivedBufLen);
+
+                        // parse packet for the octet-stream field 
+                        for (i = 0; i < receivedBufLen; i++)
+                        {
+                            if (strncmp ((char*)(receiveBuf+i), "owner", 5)==0)
+                            {
+                                DataOffset = i;
+                                break;
+                            }
+                        }
+                        // case of MSIE8 : we do not receive data in the POST packet
+                        if (DataOffset == 0)
+                        {
+                            DataFlag++;
+                            BrowserFlag = 1;
+                            //pbuf_free(p);
+                            return;
+                        }
+                        // case of Mozilla Firefox v3.6 : we receive data in the POST packet*/
+                        else
+                        {
+                            //TotalReceived = receivedBufLen - (ContentLengthOffset + 4);
+                            TotalReceived = receivedBufLen - DataOffset;
+                        }
+                    }
+                    if (((DataFlag ==1)&&(BrowserFlag==1)) || ((DataFlag ==0)&&(BrowserFlag==0)))
+                    {
+                        if ((DataFlag ==0)&&(BrowserFlag==0))
+                        {
+                            DataFlag++;
+                        }
+                        else if ((DataFlag ==1)&&(BrowserFlag==1))
+                        {
+                            // parse packet for the octet-stream field */
+                            for (i = 0; i < receivedBufLen; i++)
+                            {
+                                if (strncmp ((char*)(receiveBuf+i), "owner", 5)==0)
+                                {
+                                    DataOffset = i;
+                                    break;
+                                }
+                            }
+                            TotalReceived += receivedBufLen;
+                            DataFlag++;
+                        }
+                        TotalData =0 ;
+                    }
+                    // DataFlag >1 => the packet is data only  
+                    else
+                    {
+                        TotalReceived +=receivedBufLen;
+                    }
+    
+                    ptr = (char*)(receiveBuf + DataOffset);
+                    receivedBufLen-= DataOffset;
+
+                    // update Total data received counter 
+                    TotalData +=receivedBufLen;
+
+                    // check if last data packet 
+                    if (TotalReceived == size)
+                    {
+                        strncat(sendBuf,  ptr, receivedBufLen);
+                        strncat(sendBuf,  " ", 1);
+                        HTTP_SetInfo(sendBuf, strlen(sendBuf));
+                        DataFlag = 0;
+                        BrowserFlag = 0;
+                        memset(sendBuf, 0, size);
+
+                        strcpy(sendBuf, "HTTP/1.1 200 OK\r\n");
+                        strcat(sendBuf, "\r\n\r\n");
+                        strcat(sendBuf,"<!DOCTYPE html><html lang=""><head><meta http-equiv=\"refresh\" content=\"0;url=/info.html\"/></head></html>\r\n\r\n");
+
+                        sendBufLoadLen = strlen(sendBuf);
+                        ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                    }
+                    // not last data packet 
+                    else
+                    {
+                        // write data in flash 
+                        if(receivedBufLen)
+                        {
+                            strncat(sendBuf,  ptr, receivedBufLen);
+                            //memcpy(receiveBufTemp, ptr, receivedBufLen);
+                        }
+                    }
+                }
+            }
+            else if (strncmp(receiveBuf, "GET /history.cgi", 16) == 0)
+            {
+                int res;
+
+                res = HTTP_HistoryPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+
+                if (res == SEND_REQUIRED_FILE)
+                {
+                    ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                    
+                    //send_data(pcb, hs);
+                    //tcp_sent(pcb, http_sent_history);
+                    HTTP_SendHistory();
+                    //tcp_err(pcb, http_sent_log_err);
+                }
+                else if (res == SEND_REQUIRED_YES) 
+                {
+                    ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                }
+            }
+            else if (strncmp(receiveBuf, "GET /ups_history.cgi", 19) == 0)
+            {
+                int res;
+
+                res = HTTP_UpsHistoryPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+
+                if (res == SEND_REQUIRED_FILE)
+                {
+                    ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                    
+                    //send_data(pcb, hs);
+                    //tcp_sent(pcb, http_sent_log);
+                    HTTP_SendLog();
+                    //tcp_err(pcb, http_sent_log_err);
+                }
+                else if (res == SEND_REQUIRED_YES) 
+                {
+                    ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+                }
+            }
+            /* Тест  АКБ ИБП */
+            else if (strncmp(receiveBuf, "GET /bat_test.cgi", 17) == 0)
+            {
+                HTTP_UPSTest(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+                ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+            }
+            /* Выключение ИБП */
+            else if (strncmp(receiveBuf, "GET /ups_power.cgi", 18) == 0)
+            {
+                HTTP_UPSshutdown(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+                ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+            }
+            /* Сброс настроек и сохранине */
+            else if (strncmp(receiveBuf, "GET /reset.cgi", 14) == 0)
+            {
+                HTTP_ResetSettings();
+                HTTP_SaveSettings();
+
+                fs_open("/settings.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            /* Перезагрузка контроллера */
+            else if (strncmp(receiveBuf, "GET /reboot.cgi", 15) == 0)
+            {
+                HTTP_Reboot();
+            }
+            /* Подтверждение новых сетевых настроек */
+            else if (strncmp(receiveBuf, "GET /confirm.cgi", 16) == 0)
+            {
+                SetWebReinitFlag(false);
+                SetConfirmWebParamsFlag();
+
+                fs_open("/index.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            /* Проверка пароля, переход в bootloader */
+            else if (strncmp(receiveBuf, "GET /fw_update.cgi", 18) == 0)
+            {
+                HTTP_ConfirmBootPwd(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+                ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+            }
+            /* Смена пароля пользователя */
+            else if (strncmp(receiveBuf, "GET /changepwd.cgi", 18) == 0)
+            {
+                HTTP_ChangeUserPwd(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+            // На производстве
+            else if (strncmp(receiveBuf, "GET /setProdate.cgi", 19) == 0)
+            {
+                HTTP_Prodate(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+                ssl_sendframes(&ssl, sendBuf, sendBufLoadLen);
+            }
+            else
+            {
+                HTTP_UpdateUserLoginTime(user_id);
+                fs_open("/index.html", &file); // +
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+        }
+    //}
+        
+            
+            
+        
+        /*
+        if (strncmp(buf, "GET /main.css", 13) == 0) // +
+        {
+            fs_open("/main.css", &file);
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+        
+        else if (strncmp(buf, "GET /rotek.png", 14) == 0) // +
+        {
+            fs_open("/rotek.png", &file);
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+        else if (strncmp(buf, "GET /favicon.ico", 16) == 0) // ?                 
+        {                                                                     
+            fs_open("/favicon.ico", &file);                                     
+            ssl_sendframes(&ssl, file.data, file.len);                                          
+        }
+        else if (strncmp(buf, "GET /main.js", 12) == 0) // +
+        {
+            fs_open("/main.js", &file);
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+        else if (strncmp(buf, "GET /getJson.cgi", 16) == 0) // +
+        {
+            HTTP_GetParamsPage1(sendBuf);
+            ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+        }	
+        else if (strncmp(buf, "GET /settings.html", 18) == 0) // +
+        {
+            fs_open("/settings.html", &file);
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+        else if (strncmp(buf, "GET /info.html", 14) == 0) // +
+        {
+            fs_open("/info.html", &file);
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+        else if (strncmp(buf, "GET /getJson.cgi", 16) == 0) // +
+        {
+            HTTP_GetParamsPage1(sendBuf);
+            ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+        }	  
+        else if (strncmp(buf, "GET /settings.cgi", 17) == 0) // +
+        {
+            SET_PAGE = SET_PAGE_PAGE2;
+		
+            if (HTTP_SettingsPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen) == SEND_REQUIRED_YES)
+            {
+                ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+            }
+            else
+            {
+                fs_open("/settings.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+        }
+        else if (strncmp(buf, "GET /info.cgi", 13) == 0) // +
+        {
+            if (HTTP_InfoPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen) == SEND_REQUIRED_YES)
+            {
+                ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+            }
+            else
+            {
+                fs_open("/info.html", &file);
+                ssl_sendframes(&ssl, file.data, file.len);
+            }
+        }
+        // Сброс настроек и сохранине 
+        else if (strncmp(buf, "GET /reset.cgi", 14) == 0)
+        {
+            HTTP_ResetSettings();
+            HTTP_SaveSettings();
+		
+            fs_open("/settings.html", &file);
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+        // Перезагрузка контроллера 
+        else if (strncmp(buf, "GET /reboot.cgi", 15) == 0)
+        {
+            HTTP_Reboot();
+        }	
+        // Подтверждение новых сетевых настроек 
+        else if (strncmp(buf, "GET /confirm.cgi", 16) == 0)
+        {
+            SetWebReinitFlag(false);
+            SetConfirmWebParamsFlag();
+		
+            fs_open("/index.html", &file);
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+        // Проверка пароля, переход в bootloader 
+        else if (strncmp(buf, "POST /checkpwd.cgi", 18) == 0)
+        {
+            HTTP_ConfirmBootPwd(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+            ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+        }	
+        // На производстве
+        else if (strncmp(buf, "GET /setProdate.cgi", 19) == 0)
+        {
+            HTTP_Prodate(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+            ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+        }
+        // На производстве
+        else if (strncmp(buf, "GET /progon.cgi", 15) == 0)
+        {
+            HTTP_Progon(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen);
+            ssl_sendframes(&ssl, sendBuf, strlen(sendBuf));
+        }
+        else
+        {
+            fs_open("/index.html", &file); 
+            ssl_sendframes(&ssl, file.data, file.len);
+        }
+    // -------------------------------------------------------------------------
+    */
+    
+    // Для теста
+    
+    // 7. Write the Response 
+    //printf("\n\r => Write to client :\n\r");
+
+    // Send the dynamic html page 
+    //ssl_DynPage(&ssl);
+        
+    // Close the connection 
+    ssl_close_notify(&ssl);
+    goto accept;
+
+exit:
+    // Close and delete the current session data: certificate, RSA key and SSL session 
+    x509_free(&srvcert);
+    rsa_free(&rsa);
+    cur = s_list_1st;
+    while(cur != NULL)
+    {
+      prv = cur;
+      cur = cur->next;
+      memset(prv, 0, sizeof(ssl_session));
+      free(prv);
+    }
+    memset(&ssl, 0, sizeof(ssl_context));
+
+accept:
+    // Wait 200s until next retry 
+    vTaskDelay(200); 
+
+    // Close and free the SSL context 
+    net_close(client_fd);
+    ssl_free(&ssl);
+  }
+}           
+
+/**
+  * @brief  Create and send a dynamic Web Page.  This page contains the list of 
+  *         running tasks and the number of page hits. 
+  * @param  ssl the SSL context
+  * @retval None
+  */
+void ssl_DynPage(ssl_context *ssl)
+{
+  portCHAR buf[2024];
+  portCHAR pagehits[10];
+  portCHAR getcipher[100];
+  uint32_t len = 0;
+
+  memset(buf, 0, 2024);
+
+  // Update the hit count 
+  nPageHits++;
+  sprintf( pagehits, "%d", nPageHits );
+  sprintf( (char *) getcipher, HTTP_RESPONSE, ssl_get_ciphersuite(ssl));   
+  
+  // Generate the dynamic page 
+  strcpy(buf, PAGE_START);
+
+  // Page header 
+  strcat(buf, pagehits);
+  strcat((char *) buf, "<br><pre>** The list of tasks and their status **");
+  strcat((char *) buf, "<br><pre>---------------------------------------------"); 
+  strcat((char *) buf, "<br>Name          State  Priority  Stack   Num" );
+  //strcat((char *) buf, "<br>---------------------------------------------"); 
+  strcat((char *) buf, "<br>---------------------------------------------<br>"); 
+    
+  // The list of tasks and their status 
+  vTaskList((signed char *)buf + strlen(buf));
+  strcat((char *) buf, "<br>---------------------------------------------"); 
+  strcat((char *) buf, "<br>B : Blocked, R : Ready, D : Deleted, S : Suspended");
+
+  // The current cipher used 
+  strcat(buf, getcipher);
+
+  // Page footer 
+  strcat(buf, PAGE_END);
+  
+  // Send the dynamically generated page 
+  len = ssl_write(ssl, (unsigned char *)buf, strlen(buf));
+
+  // Display the length of application data 
+  //printf( "\n Successfully write %d bytes to client\n\r", len);
+}
+
+/**
+  * @brief  This function is used to send messages with size upper 16k bytes.
+  * @param  ssl  SSL context
+  * @param  data buffer holding the data
+  * @param  len  how many bytes must be written
+  * @retval None
+  */
+#define FRAME_SIZE   (1000)
+void ssl_sendframes( ssl_context *ssl, char *data, int datalen )
+{
+  int index = 0;
+  int k = 0;
+  int lastframe, nbrframes;
+
+  // Calculate the number of frames 
+  nbrframes = datalen / FRAME_SIZE; 
+  
+  // Send nbrframes frames 
+  while(nbrframes > 0)
+  {
+    index = k * FRAME_SIZE;
+    ssl_write( ssl, (unsigned char *)(data + index), FRAME_SIZE );
+    nbrframes--;
+    k++;
+  }
+  // Send the last frame 
+  index = k * FRAME_SIZE;
+  lastframe = datalen % FRAME_SIZE ;
+  ssl_write( ssl, (unsigned char *)(data + index), lastframe );
+}
+
+/**
+  * @brief  Returns a 32-bit random number.
+  * @param  arg not used
+  * @retval 32-bit random number
+  */
+int RandVal(void* arg)
+{
+  return (int)GetRandomNumber();
+}
+
+/**
+  * @brief Send callback for log file transfer (messages as is, not ordered)
+  */
+void HTTP_SendHistory(void)
+{
+    uint32_t nbytes = 0;
+    static bool start = true;
+
+    memset(logFileBuf, 0, FILE_BUF_MAX_LEN);
+    
+    if (log_ptr + FILE_BUF_MAX_LEN <= log_size) {
+        nbytes = History_GetData(log_ptr, logFileBuf, FILE_BUF_MAX_LEN, start);
+    }
+    else if (log_ptr < log_size) {
+        nbytes = History_GetData(log_ptr, logFileBuf, (log_size - log_ptr), start);
+    }
+    else {
+        nbytes = 0;
+    }
+    log_ptr += nbytes;
+
+    start = false;
+    
+    if (nbytes == 0) {
+        // File transfer finished. 
+        start = true;
+        // Clear file transfer in progress flag 
+        fLogTransInprog = false;
+        return;
+    }
+
+    ssl_sendframes(&ssl, logFileBuf, nbytes);
+    HTTP_SendHistory();
+}
+
+
+/**
+  * @brief Sent callback for log file transfer (messages as is, not ordered)
+  */
+void HTTP_SendLog(void)
+{
+    uint32_t nbytes = 0;
+    static bool start = true;
+
+	memset(logFileBuf, 0, FILE_BUF_MAX_LEN);
+    if (log_ptr + FILE_BUF_MAX_LEN_LOG <= log_size) {
+        nbytes = LOG_GetData(log_ptr, logFileBuf, FILE_BUF_MAX_LEN_LOG, start);
+    }
+    else if (log_ptr < log_size) {
+        nbytes = LOG_GetData(log_ptr, logFileBuf, (log_size - log_ptr), start);
+    }
+    else {
+        nbytes = 0;
+    }
+    log_ptr += nbytes;
+
+    start = false;
+    if (nbytes == 0) {
+        // File transfer finished. 
+        start = true;
+        // Clear file transfer in progress flag 
+        fLogTransInprog = false;
+        return;
+    }
+
+    ssl_sendframes(&ssl, logFileBuf, nbytes);
+    HTTP_SendLog();
+  
+    return;
+}
+
+/**
+  * @brief  Initialize the HTTPS server (start its thread) 
+  */
+void HTTPS_Init()
+{
+	char buf[MAX_WEB_COOKIE_LEN];
+	uint8_t user_id;
+    
+    for (user_id = 0; user_id < MAX_WEB_USERS; user_id++) {
+        // Flush user cookie by random value 
+        sprintf(buf, "%X", (unsigned int)GetRandomNumber());
+        HTTP_SetUserCookie(buf, user_id);
+
+        // Create user logout timers 
+        users[user_id].LogoutTimer =
+             xTimerCreate("LogoutTmr", WEB_LOGOUT_TIME, pdFALSE, ( void * ) user_id, LogoutTimerCallback);
+    }
+}

+ 37 - 0
modules/HTTP_Server/http_server.h

@@ -118,3 +118,40 @@ void ClearParamString(char *inBuf);
   * @param  sim2 - символ на который надо заменить
   */
 void HTTP_ReplaceSimbol(char *str, char sim1, char sim2);
+
+
+// -----------------------------------------------------------------------------
+//
+//
+//  SSL тесты
+//
+//
+// -----------------------------------------------------------------------------
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "polarssl/ssl.h"
+
+/* Exported types ------------------------------------------------------------*/
+typedef struct
+{
+  uint32_t State;
+}rng_state;
+
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+void ssl_server(void *pvParameters);
+void ssl_DynPage(ssl_context *ssl);
+void ssl_sendframes(ssl_context *ssl, char *data, int datalen);
+int RandVal(void* arg);
+void HTTP_SendHistory(void);
+void HTTP_SendLog(void);
+void HTTPS_Init();
+
+#ifdef __cplusplus
+}
+#endif

+ 9 - 0
modules/Makefile

@@ -25,6 +25,7 @@ INCLUDES += -I../stm32/system
 INCLUDES += -I../peripheral_modules/inc
 INCLUDES += -I../user
 INCLUDES += -I../thirdparty/TinyStdio
+INCLUDES += -I../thirdparty/myStrings
 INCLUDES += -I.
 
 CSRC = $(wildcard ../stm32/stm32f4xx_spl/src/*.c)
@@ -32,6 +33,7 @@ CSRC += $(wildcard ../stm32/system/*.c)
 CSRC += $(wildcard ../peripheral_modules/src/*.c)
 CSRC += $(wildcard ../user/*.c)
 CSRC += $(wildcard ../thirdparty/TinyStdio/*.c)
+CSRC += $(wildcard ../thirdparty/myStrings/*.c)
 CSRC += $(wildcard *.c)
 
 INCLUDES += -Ileds
@@ -93,6 +95,13 @@ CSRC += $(wildcard ../thirdparty/FreeRTOS/portable/MemMang/heap_4.c)
   	CSRC += $(wildcard STM32F4x7_ETH_Driver/*.c)
     
 CSRC += $(wildcard ../stm32/system/syscalls/syscalls.c)
+
+#SSL
+
+INCLUDES += -I../thirdparty/PolarSSL/include/polarssl/
+INCLUDES += -I../thirdparty/PolarSSL/include/
+
+CSRC += $(wildcard ../thirdparty/PolarSSL/library/*.c)
     
     
 CFLAGS += -DUSE_STDPERIPH_DRIVER -DSTM32F40_41xxx -DLOG_ENABLE

+ 2 - 2
modules/startup/stm32_flash.ld

@@ -36,8 +36,8 @@ ENTRY(Reset_Handler)
 _estack = 0x2001ffff;    /* end of 128K RAM on AHB bus*/
 
 /* Generate a link error if heap and stack don't fit into RAM */
-_Min_Heap_Size = 0x100;      /* required amount of heap  */
-_Min_Stack_Size = 0x100; /* required amount of stack */
+_Min_Heap_Size = 0x3000;      /* required amount of heap  */
+_Min_Stack_Size = 0x4000; /* required amount of stack */
 
 /* Specify the memory areas */
 MEMORY

binární
output/BT_6702xx.bin


binární
output/stm32bt6702.bin


+ 6 - 0
peripheral_modules/inc/rtc.h

@@ -463,6 +463,12 @@ void RTC_SetDebugProfTime(void);
   */
 void RTC_SetProfTime(char *date);
 
+/**
+  * @brief  
+  * @retval 
+  */
+uint32_t RTC_GetUnixTime(void);
+
 /* C++ detection */
 #ifdef __cplusplus
 }

+ 16 - 16
peripheral_modules/src/rng.c

@@ -1,16 +1,16 @@
-#include <stdint.h>
-#include "rng.h"
-#include "stm32f4xx.h"
-
-
-void RNG_Init(void)
-{
-    RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG,ENABLE);
-    RNG_Cmd(ENABLE);
-}
-
-uint32_t GetRandomNumber(void) {
-    return RNG_GetRandomNumber();;
-}
-
-
+#include <stdint.h>
+#include "rng.h"
+#include "stm32f4xx.h"
+
+
+void RNG_Init(void)
+{
+    RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG,ENABLE);
+    RNG_Cmd(ENABLE);
+}
+
+uint32_t GetRandomNumber(void) {
+    return RNG_GetRandomNumber();
+}
+
+

+ 14 - 1
peripheral_modules/src/rtc.c

@@ -861,4 +861,17 @@ void RTC_SetProfTime(char *str)
   tmp.year += 1;
   unixTime = TM_RTC_GetUnixTimeStamp(&tmp);  
   TM_RTC_WriteBackupRegister(RTC_BKP_DR0, unixTime);
-}
+}
+
+/**
+  * @brief  
+  * @retval 
+  */
+uint32_t RTC_GetUnixTime(void)
+{
+  TM_RTC_t currentTime;
+  
+  TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
+  return TM_RTC_GetUnixTimeStamp(&currentTime);
+}
+

+ 108 - 1
projects/iar/bt-670x.ewp

@@ -343,6 +343,8 @@
           <state>$PROJ_DIR$\..\..\thirdparty\lwip\src\include\ipv4</state>
           <state>$PROJ_DIR$\..\..\thirdparty\lwip\port</state>
           <state>$PROJ_DIR$\..\..\thirdparty\lwip\arch</state>
+          <state>$PROJ_DIR$\..\..\thirdparty\PolarSSL\include\polarssl</state>
+          <state>$PROJ_DIR$\..\..\thirdparty\PolarSSL\include</state>
         </option>
         <option>
           <name>CCStdIncCheck</name>
@@ -642,7 +644,7 @@
         </option>
         <option>
           <name>OOCObjCopyEnable</name>
-          <state>0</state>
+          <state>1</state>
         </option>
       </data>
     </settings>
@@ -1980,6 +1982,9 @@
     </group>
     <group>
       <name>ethernet</name>
+      <file>
+        <name>$PROJ_DIR$\..\..\modules\Ethernet\lwipopts.h</name>
+      </file>
       <file>
         <name>$PROJ_DIR$\..\..\modules\Ethernet\netconf.c</name>
       </file>
@@ -2395,6 +2400,108 @@
         </file>
       </group>
     </group>
+    <group>
+      <name>polarssl</name>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\aes.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\arc4.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\base64.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\bignum.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\camellia.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\certs.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\cipher.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\cipher_wrap.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\debug.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\des.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\dhm.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\error.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\havege.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\md.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\md2.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\md4.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\md5.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\md_wrap.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\net.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\padlock.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\pem.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\pkcs11.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\rsa.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\sha1.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\sha2.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\sha4.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\ssl_cli.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\ssl_srv.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\ssl_tls.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\timing.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\version.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\x509parse.c</name>
+      </file>
+      <file>
+        <name>$PROJ_DIR$\..\..\thirdparty\PolarSSL\library\xtea.c</name>
+      </file>
+    </group>
   </group>
   <group>
     <name>user</name>

+ 10 - 0
stm32/system/syscalls/syscalls.c

@@ -11,6 +11,9 @@
 #include "stm32f4xx_usart.h"
 #include "stm32f4xx.h"
 
+#include "rtc.h"
+#include "lwip/sockets.h"
+
 #ifdef SWOTRACE
 /* Set STDIO_USART to 255 as flag that trace output on SWO pin used instead */
 #define STDIO_USART 255
@@ -299,3 +302,10 @@ int _write(int file, char *ptr, int len) {
     }
     return len;
 }
+
+int _gettimeofday( struct timeval *tv, void *tzvp )
+{
+    tv->tv_sec = RTC_GetUnixTime();  // convert to seconds
+    tv->tv_usec = 0;  // get remaining microseconds
+    return 0;  // return non-zero for error
+}

+ 38 - 0
thirdparty/PolarSSL/CMakeLists.txt

@@ -0,0 +1,38 @@
+cmake_minimum_required(VERSION 2.6)
+project(POLARSSL C)
+
+enable_testing()
+
+if(CMAKE_COMPILER_IS_GNUCC)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -Wdeclaration-after-statement")
+  set(CMAKE_C_FLAGS_DEBUG "-g -O0")
+  set(CMAKE_C_FLAGS_COVERAGE "-g -O0 -fprofile-arcs -ftest-coverage -lgcov")
+endif(CMAKE_COMPILER_IS_GNUCC)
+ 
+if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
+  if(CMAKE_COMPILER_IS_GNUCC)
+    set(CMAKE_SHARED_LINKER_FLAGS "-fprofile-arcs -ftest-coverage")
+  endif(CMAKE_COMPILER_IS_GNUCC)
+endif(CMAKE_BUILD_TYPE STREQUAL "Coverage")
+
+option(USE_PKCS11_HELPER_LIBRARY "Build PolarSSL with the pkcs11-helper library." OFF)
+
+if(LIB_INSTALL_DIR)
+else()
+set(LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib)
+endif()
+
+include_directories(include/)
+
+add_subdirectory(library)
+add_subdirectory(include)
+
+if(CMAKE_COMPILER_IS_GNUCC)
+  add_subdirectory(tests)
+endif(CMAKE_COMPILER_IS_GNUCC)
+
+add_subdirectory(programs)
+
+ADD_CUSTOM_TARGET(apidoc
+                  COMMAND doxygen doxygen/polarssl.doxyfile
+                  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

+ 441 - 0
thirdparty/PolarSSL/ChangeLog

@@ -0,0 +1,441 @@
+PolarSSL ChangeLog
+
+= Version 1.0.0 released on 2011-07-27
+Features
+   * Expanded cipher layer with support for CFB128 and CTR mode
+   * Added rsa_encrypt and rsa_decrypt simple example programs.
+
+Changes
+   * The generic cipher and message digest layer now have normal error
+     codes instead of integers
+
+Bugfix
+   * Undid faulty bug fix in ssl_write() when flushing old data (Ticket
+     #18)
+
+= Version 0.99-pre5 released on 2011-05-26
+Features
+   * Added additional Cipher Block Modes to symmetric ciphers
+     (AES CTR, Camellia CTR, XTEA CBC) including the option to
+	 enable and disable individual modes when needed
+   * Functions requiring File System functions can now be disabled
+     by undefining POLARSSL_FS_IO
+   * A error_strerror function() has been added to translate between
+     error codes and their description.
+   * Added mpi_get_bit() and mpi_set_bit() individual bit setter/getter
+     functions.
+   * Added ssl_mail_client and ssl_fork_server as example programs.
+
+Changes
+   * Major argument / variable rewrite. Introduced use of size_t
+     instead of int for buffer lengths and loop variables for
+	 better unsigned / signed use. Renamed internal bigint types
+	 t_int and t_dbl to t_uint and t_udbl in the process
+   * mpi_init() and mpi_free() now only accept a single MPI
+     argument and do not accept variable argument lists anymore.
+   * The error codes have been remapped and combining error codes
+     is now done with a PLUS instead of an OR as error codes
+	 used are negative.
+   * Changed behaviour of net_read(), ssl_fetch_input() and ssl_recv().
+     net_recv() now returns 0 on EOF instead of
+	 POLARSSL_ERR_NET_CONN_RESET. ssl_fetch_input() returns
+	 POLARSSL_ERR_SSL_CONN_EOF on an EOF from its f_recv() function.
+	 ssl_read() returns 0 if a POLARSSL_ERR_SSL_CONN_EOF is received
+	 after the handshake.
+   * Network functions now return POLARSSL_ERR_NET_WANT_READ or
+     POLARSSL_ERR_NET_WANT_WRITE instead of the ambiguous
+	 POLARSSL_ERR_NET_TRY_AGAIN
+
+= Version 0.99-pre4 released on 2011-04-01
+Features
+   * Added support for PKCS#1 v2.1 encoding and thus support
+     for the RSAES-OAEP and RSASSA-PSS operations.
+   * Reading of Public Key files incorporated into default x509
+     functionality as well.
+   * Added mpi_fill_random() for centralized filling of big numbers
+     with random data (Fixed ticket #10)
+
+Changes
+   * Debug print of MPI now removes leading zero octets and 
+     displays actual bit size of the value.
+   * x509parse_key() (and as a consequence x509parse_keyfile()) 
+     does not zeroize memory in advance anymore. Use rsa_init()
+	 before parsing a key or keyfile!
+
+Bugfix
+   * Debug output of MPI's now the same independent of underlying
+     platform (32-bit / 64-bit) (Fixes ticket #19, found by Mads
+	 Kiilerich and Mihai Militaru)
+   * Fixed bug in ssl_write() when flushing old data (Fixed ticket
+     #18, found by Nikolay Epifanov)
+   * Fixed proper handling of RSASSA-PSS verification with variable
+     length salt lengths
+
+= Version 0.99-pre3 released on 2011-02-28
+This release replaces version 0.99-pre2 which had possible copyright issues.
+Features
+   * Parsing PEM private keys encrypted with DES and AES
+     are now supported as well (Fixes ticket #5)
+   * Added crl_app program to allow easy reading and
+     printing of X509 CRLs from file
+
+Changes
+   * Parsing of PEM files moved to separate module (Fixes 
+     ticket #13). Also possible to remove PEM support for
+	 systems only using DER encoding
+
+Bugfixes
+   * Corrected parsing of UTCTime dates before 1990 and
+     after 1950
+   * Support more exotic OID's when parsing certificates
+   	 (found by Mads Kiilerich)
+   * Support more exotic name representations when parsing
+     certificates (found by Mads Kiilerich)
+   * Replaced the expired test certificates
+   * Do not bail out if no client certificate specified. Try
+     to negotiate anonymous connection (Fixes ticket #12,
+	 found by Boris Krasnovskiy)
+
+Security fixes
+   * Fixed a possible Man-in-the-Middle attack on the
+     Diffie Hellman key exchange (thanks to Larry Highsmith,
+	 Subreption LLC)
+
+= Version 0.99-pre1 released on 2011-01-30
+Features
+Note: Most of these features have been donated by Fox-IT
+   * Added Doxygen source code documentation parts
+   * Added reading of DHM context from memory and file
+   * Improved X509 certificate parsing to include extended
+     certificate fields, including Key Usage
+   * Improved certificate verification and verification
+     against the available CRLs
+   * Detection for DES weak keys and parity bits added
+   * Improvements to support integration in other
+     applications:
+       + Added generic message digest and cipher wrapper
+       + Improved information about current capabilities,
+         status, objects and configuration
+       + Added verification callback on certificate chain
+         verification to allow external blacklisting
+	   + Additional example programs to show usage
+   * Added support for PKCS#11 through the use of the
+     libpkcs11-helper library
+
+Changes
+   * x509parse_time_expired() checks time in addition to
+     the existing date check
+   * The ciphers member of ssl_context and the cipher member
+     of ssl_session have been renamed to ciphersuites and
+	 ciphersuite respectively. This clarifies the difference
+	 with the generic cipher layer and is better naming
+	 altogether
+
+= Version 0.14.0 released on 2010-08-16
+Features
+   * Added support for SSL_EDH_RSA_AES_128_SHA and
+     SSL_EDH_RSA_CAMELLIA_128_SHA ciphersuites
+   * Added compile-time and run-time version information
+   * Expanded ssl_client2 arguments for more flexibility
+   * Added support for TLS v1.1
+
+Changes
+   * Made Makefile cleaner
+   * Removed dependency on rand() in rsa_pkcs1_encrypt().
+     Now using random fuction provided to function and
+	 changed the prototype of rsa_pkcs1_encrypt(),
+	 rsa_init() and rsa_gen_key().
+   * Some SSL defines were renamed in order to avoid
+     future confusion
+
+Bug fixes
+   * Fixed CMake out of source build for tests (found by
+     kkert)
+   * rsa_check_private() now supports PKCS1v2 keys as well
+   * Fixed deadlock in rsa_pkcs1_encrypt() on failing random
+     generator
+
+= Version 0.13.1 released on 2010-03-24
+Bug fixes
+   * Fixed Makefile in library that was mistakenly merged
+   * Added missing const string fixes
+
+= Version 0.13.0 released on 2010-03-21
+Features
+   * Added option parsing for host and port selection to
+     ssl_client2
+   * Added support for GeneralizedTime in X509 parsing
+   * Added cert_app program to allow easy reading and
+     printing of X509 certificates from file or SSL
+     connection.
+
+Changes
+   * Added const correctness for main code base
+   * X509 signature algorithm determination is now
+     in a function to allow easy future expansion
+   * Changed symmetric cipher functions to
+     identical interface (returning int result values)
+   * Changed ARC4 to use seperate input/output buffer
+   * Added reset function for HMAC context as speed-up
+     for specific use-cases
+
+Bug fixes
+   * Fixed bug resulting in failure to send the last
+     certificate in the chain in ssl_write_certificate() and
+     ssl_write_certificate_request() (found by fatbob)
+   * Added small fixes for compiler warnings on a Mac
+     (found by Frank de Brabander)
+   * Fixed algorithmic bug in mpi_is_prime() (found by
+     Smbat Tonoyan)
+
+= Version 0.12.1 released on 2009-10-04
+Changes
+   * Coverage test definitions now support 'depends_on'
+     tagging system.
+   * Tests requiring specific hashing algorithms now honor
+     the defines.
+
+Bug fixes
+   * Changed typo in #ifdef in x509parse.c (found
+     by Eduardo)
+
+= Version 0.12.0 released on 2009-07-28
+Features
+   * Added CMake makefiles as alternative to regular Makefiles.
+   * Added preliminary Code Coverage tests for AES, ARC4,
+     Base64, MPI, SHA-family, MD-family, HMAC-SHA-family,
+     Camellia, DES, 3-DES, RSA PKCS#1, XTEA, Diffie-Hellman
+     and X509parse.
+
+Changes
+   * Error codes are not (necessarily) negative. Keep
+     this is mind when checking for errors.
+   * RSA_RAW renamed to SIG_RSA_RAW for consistency.
+   * Fixed typo in name of POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE.
+   * Changed interface for AES and Camellia setkey functions
+     to indicate invalid key lengths.
+
+Bug fixes
+   * Fixed include location of endian.h on FreeBSD (found by
+     Gabriel)
+   * Fixed include location of endian.h and name clash on
+     Apples (found by Martin van Hensbergen)
+   * Fixed HMAC-MD2 by modifying md2_starts(), so that the
+     required HMAC ipad and opad variables are not cleared.
+     (found by code coverage tests)
+   * Prevented use of long long in bignum if 
+     POLARSSL_HAVE_LONGLONG not defined (found by Giles
+     Bathgate).
+   * Fixed incorrect handling of negative strings in
+     mpi_read_string() (found by code coverage tests).
+   * Fixed segfault on handling empty rsa_context in
+     rsa_check_pubkey() and rsa_check_privkey() (found by
+     code coverage tests).
+   * Fixed incorrect handling of one single negative input
+     value in mpi_add_abs() (found by code coverage tests).
+   * Fixed incorrect handling of negative first input
+     value in mpi_sub_abs() (found by code coverage tests).
+   * Fixed incorrect handling of negative first input
+     value in mpi_mod_mpi() and mpi_mod_int(). Resulting
+     change also affects mpi_write_string() (found by code
+     coverage tests).
+   * Corrected is_prime() results for 0, 1 and 2 (found by
+     code coverage tests).
+   * Fixed Camellia and XTEA for 64-bit Windows systems.
+
+= Version 0.11.1 released on 2009-05-17
+   * Fixed missing functionality for SHA-224, SHA-256, SHA384,
+     SHA-512 in rsa_pkcs1_sign()
+
+= Version 0.11.0 released on 2009-05-03
+   * Fixed a bug in mpi_gcd() so that it also works when both
+     input numbers are even and added testcases to check
+     (found by Pierre Habouzit).
+   * Added support for SHA-224, SHA-256, SHA-384 and SHA-512
+     one way hash functions with the PKCS#1 v1.5 signing and
+     verification.
+   * Fixed minor bug regarding mpi_gcd located within the
+     POLARSSL_GENPRIME block.
+   * Fixed minor memory leak in x509parse_crt() and added better
+     handling of 'full' certificate chains (found by Mathias
+     Olsson).
+   * Centralized file opening and reading for x509 files into
+     load_file()
+   * Made definition of net_htons() endian-clean for big endian
+     systems (Found by Gernot).
+   * Undefining POLARSSL_HAVE_ASM now also handles prevents asm in
+     padlock and timing code. 
+   * Fixed an off-by-one buffer allocation in ssl_set_hostname()
+     responsible for crashes and unwanted behaviour.
+   * Added support for Certificate Revocation List (CRL) parsing.
+   * Added support for CRL revocation to x509parse_verify() and
+     SSL/TLS code.
+   * Fixed compatibility of XTEA and Camellia on a 64-bit system
+     (found by Felix von Leitner).
+
+= Version 0.10.0 released on 2009-01-12
+   * Migrated XySSL to PolarSSL
+   * Added XTEA symmetric cipher
+   * Added Camellia symmetric cipher
+   * Added support for ciphersuites: SSL_RSA_CAMELLIA_128_SHA,
+     SSL_RSA_CAMELLIA_256_SHA and SSL_EDH_RSA_CAMELLIA_256_SHA
+   * Fixed dangerous bug that can cause a heap overflow in
+     rsa_pkcs1_decrypt (found by Christophe Devine)
+
+================================================================
+XySSL ChangeLog
+
+= Version 0.9 released on 2008-03-16
+
+    * Added support for ciphersuite: SSL_RSA_AES_128_SHA
+    * Enabled support for large files by default in aescrypt2.c
+    * Preliminary openssl wrapper contributed by David Barrett
+    * Fixed a bug in ssl_write() that caused the same payload to
+      be sent twice in non-blocking mode when send returns EAGAIN
+    * Fixed ssl_parse_client_hello(): session id and challenge must
+      not be swapped in the SSLv2 ClientHello (found by Greg Robson)
+    * Added user-defined callback debug function (Krystian Kolodziej)
+    * Before freeing a certificate, properly zero out all cert. data
+    * Fixed the "mode" parameter so that encryption/decryption are
+      not swapped on PadLock; also fixed compilation on older versions
+      of gcc (bug reported by David Barrett)
+    * Correctly handle the case in padlock_xcryptcbc() when input or
+      ouput data is non-aligned by falling back to the software
+      implementation, as VIA Nehemiah cannot handle non-aligned buffers
+    * Fixed a memory leak in x509parse_crt() which was reported by Greg
+      Robson-Garth; some x509write.c fixes by Pascal Vizeli, thanks to
+      Matthew Page who reported several bugs
+    * Fixed x509_get_ext() to accept some rare certificates which have
+      an INTEGER instead of a BOOLEAN for BasicConstraints::cA.
+    * Added support on the client side for the TLS "hostname" extension
+      (patch contributed by David Patino)
+    * Make x509parse_verify() return BADCERT_CN_MISMATCH when an empty
+      string is passed as the CN (bug reported by spoofy)
+    * Added an option to enable/disable the BN assembly code
+    * Updated rsa_check_privkey() to verify that (D*E) = 1 % (P-1)*(Q-1)
+    * Disabled obsolete hash functions by default (MD2, MD4); updated
+      selftest and benchmark to not test ciphers that have been disabled
+    * Updated x509parse_cert_info() to correctly display byte 0 of the
+      serial number, setup correct server port in the ssl client example
+    * Fixed a critical denial-of-service with X.509 cert. verification:
+      peer may cause xyssl to loop indefinitely by sending a certificate
+      for which the RSA signature check fails (bug reported by Benoit)
+    * Added test vectors for: AES-CBC, AES-CFB, DES-CBC and 3DES-CBC,
+      HMAC-MD5, HMAC-SHA1, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512
+    * Fixed HMAC-SHA-384 and HMAC-SHA-512 (thanks to Josh Sinykin)
+    * Modified ssl_parse_client_key_exchange() to protect against
+      Daniel Bleichenbacher attack on PKCS#1 v1.5 padding, as well
+      as the Klima-Pokorny-Rosa extension of Bleichenbacher's attack
+    * Updated rsa_gen_key() so that ctx->N is always nbits in size
+    * Fixed assembly PPC compilation errors on Mac OS X, thanks to
+      David Barrett and Dusan Semen
+
+= Version 0.8 released on 2007-10-20
+
+    * Modified the HMAC functions to handle keys larger
+      than 64 bytes, thanks to Stephane Desneux and gary ng
+    * Fixed ssl_read_record() to properly update the handshake
+      message digests, which fixes IE6/IE7 client authentication
+    * Cleaned up the XYSSL* #defines, suggested by Azriel Fasten
+    * Fixed net_recv(), thanks to Lorenz Schori and Egon Kocjan
+    * Added user-defined callbacks for handling I/O and sessions
+    * Added lots of debugging output in the SSL/TLS functions
+    * Added preliminary X.509 cert. writing by Pascal Vizeli
+    * Added preliminary support for the VIA PadLock routines
+    * Added AES-CFB mode of operation, contributed by chmike
+    * Added an SSL/TLS stress testing program (ssl_test.c)
+    * Updated the RSA PKCS#1 code to allow choosing between
+      RSA_PUBLIC and RSA_PRIVATE, as suggested by David Barrett
+    * Updated ssl_read() to skip 0-length records from OpenSSL
+    * Fixed the make install target to comply with *BSD make
+    * Fixed a bug in mpi_read_binary() on 64-bit platforms
+    * mpi_is_prime() speedups, thanks to Kevin McLaughlin
+    * Fixed a long standing memory leak in mpi_is_prime()
+    * Replaced realloc with malloc in mpi_grow(), and set
+      the sign of zero as positive in mpi_init() (reported
+      by Jonathan M. McCune)
+
+= Version 0.7 released on 2007-07-07
+
+    * Added support for the MicroBlaze soft-core processor
+    * Fixed a bug in ssl_tls.c which sometimes prevented SSL
+      connections from being established with non-blocking I/O
+    * Fixed a couple bugs in the VS6 and UNIX Makefiles
+    * Fixed the "PIC register ebx clobbered in asm" bug
+    * Added HMAC starts/update/finish support functions
+    * Added the SHA-224, SHA-384 and SHA-512 hash functions
+    * Fixed the net_set_*block routines, thanks to Andreas
+    * Added a few demonstration programs: md5sum, sha1sum,
+      dh_client, dh_server, rsa_genkey, rsa_sign, rsa_verify
+    * Added new bignum import and export helper functions
+    * Rewrote README.txt in program/ssl/ca to better explain
+      how to create a test PKI
+
+= Version 0.6 released on 2007-04-01
+
+    * Ciphers used in SSL/TLS can now be disabled at compile
+      time, to reduce the memory footprint on embedded systems
+    * Added multiply assembly code for the TriCore and modified
+      havege_struct for this processor, thanks to David Patiño
+    * Added multiply assembly code for 64-bit PowerPCs,
+      thanks to Peking University and the OSU Open Source Lab
+    * Added experimental support of Quantum Cryptography
+    * Added support for autoconf, contributed by Arnaud Cornet
+    * Fixed "long long" compilation issues on IA-64 and PPC64
+    * Fixed a bug introduced in xyssl-0.5/timing.c: hardclock
+      was not being correctly defined on ARM and MIPS
+
+= Version 0.5 released on 2007-03-01
+
+    * Added multiply assembly code for SPARC and Alpha
+    * Added (beta) support for non-blocking I/O operations
+    * Implemented session resuming and client authentication
+    * Fixed some portability issues on WinCE, MINIX 3, Plan9
+      (thanks to Benjamin Newman), HP-UX, FreeBSD and Solaris
+    * Improved the performance of the EDH key exchange
+    * Fixed a bug that caused valid packets with a payload
+      size of 16384 bytes to be rejected
+
+= Version 0.4 released on 2007-02-01
+
+    * Added support for Ephemeral Diffie-Hellman key exchange
+    * Added multiply asm code for SSE2, ARM, PPC, MIPS and M68K
+    * Various improvement to the modular exponentiation code
+    * Rewrote the headers to generate the API docs with doxygen
+    * Fixed a bug in ssl_encrypt_buf (incorrect padding was
+      generated) and in ssl_parse_client_hello (max. client
+      version was not properly set), thanks to Didier Rebeix
+    * Fixed another bug in ssl_parse_client_hello: clients with
+      cipherlists larger than 96 bytes were incorrectly rejected
+    * Fixed a couple memory leak in x509_read.c
+
+= Version 0.3 released on 2007-01-01
+
+    * Added server-side SSLv3 and TLSv1.0 support
+    * Multiple fixes to enhance the compatibility with g++,
+      thanks to Xosé Antón Otero Ferreira
+    * Fixed a bug in the CBC code, thanks to dowst; also,
+      the bignum code is no longer dependant on long long
+    * Updated rsa_pkcs1_sign to handle arbitrary large inputs
+    * Updated timing.c for improved compatibility with i386
+      and 486 processors, thanks to Arnaud Cornet
+
+= Version 0.2 released on 2006-12-01
+
+    * Updated timing.c to support ARM and MIPS arch
+    * Updated the MPI code to support 8086 on MSVC 1.5
+    * Added the copyright notice at the top of havege.h
+    * Fixed a bug in sha2_hmac, thanks to newsoft/Wenfang Zhang
+    * Fixed a bug reported by Adrian Rüegsegger in x509_read_key
+    * Fixed a bug reported by Torsten Lauter in ssl_read_record
+    * Fixed a bug in rsa_check_privkey that would wrongly cause
+      valid RSA keys to be dismissed (thanks to oldwolf)
+    * Fixed a bug in mpi_is_prime that caused some primes to fail
+      the Miller-Rabin primality test
+
+    I'd also like to thank Younès Hafri for the CRUX linux port,
+    Khalil Petit who added XySSL into pkgsrc and Arnaud Cornet
+    who maintains the Debian package :-)
+
+= Version 0.1 released on 2006-11-01
+

+ 3 - 0
thirdparty/PolarSSL/DartConfiguration.tcl

@@ -0,0 +1,3 @@
+Site: localhost
+BuildName: PolarSSL-test
+CoverageCommand: /usr/bin/gcov

+ 339 - 0
thirdparty/PolarSSL/LICENSE

@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

+ 44 - 0
thirdparty/PolarSSL/Makefile

@@ -0,0 +1,44 @@
+
+DESTDIR=/usr/local
+PREFIX=polarssl_
+
+.SILENT:
+
+all:
+	cd library  && $(MAKE) all && cd ..
+	cd programs && $(MAKE) all && cd ..
+	cd tests    && $(MAKE) all && cd ..
+
+install:
+	mkdir -p $(DESTDIR)/include/polarssl
+	cp -r include/polarssl $(DESTDIR)/include
+	
+	mkdir -p $(DESTDIR)/lib
+	cp library/libpolarssl.* $(DESTDIR)/lib
+	
+	mkdir -p $(DESTDIR)/bin
+	for p in programs/*/* ; do              \
+	    if [ -x $$p ] && [ ! -d $$p ] ;     \
+	    then                                \
+	        f=$(PREFIX)`basename $$p` ;     \
+	        cp $$p $(DESTDIR)/bin/$$f ;     \
+	    fi                                  \
+	done
+
+clean:
+	cd library  && $(MAKE) clean && cd ..
+	cd programs && $(MAKE) clean && cd ..
+	cd tests    && $(MAKE) clean && cd ..
+
+check:
+	( cd tests && $(MAKE) check )
+
+apidoc:
+	mkdir -p apidoc
+	doxygen doxygen/polarssl.doxyfile
+
+apidoc_clean:
+	if [ -d apidoc ] ;			\
+	then				    	\
+		rm -rf apidoc ;			\
+	fi

+ 40 - 0
thirdparty/PolarSSL/README

@@ -0,0 +1,40 @@
+README for PolarSSL
+
+-- COMPILING
+There are currently three active build systems within the PolarSSL releases:
+ - Make
+ - CMake
+ - Microsoft Visual Studio
+
+The main system used for development is CMake. That system is always the most up-to-date. The others should reflect all changes present in the CMake build system, but some features are not ported there by default.
+
+--- Make
+In order to build the source using Make, just enter at the command line:
+make
+
+In order to run the tests, enter:
+make check
+
+--- CMake
+In order to build the source using CMake, just enter at the command line:
+cmake .
+make
+
+There are 3 different active build modes specified within the CMake buildsystem:
+ - Release
+   This generates the default code without any unnecessary information in the binary files.
+ - Debug
+   This generates debug information and disables optimization of the code.
+ - Coverage
+   This generates code coverage information in addition to debug information.
+
+Switching build modes in CMake is simple. For debug mode, enter at the command line:
+cmake -D CMAKE_BUILD_TYPE:String="Debug" .
+
+In order to run the tests, enter:
+make test
+
+--- Microsoft Visual Studio
+The build files for Microsoft Visual Studio are generated for Visual Studio 6.0 all future Visual Studio's should be able to open and use this older version of the build files.
+
+The workspace 'polarssl.dsw' contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need a perl environment as well.

+ 32 - 0
thirdparty/PolarSSL/contrib/indent.sh

@@ -0,0 +1,32 @@
+#!/bin/sh
+
+indent --blank-lines-after-declarations         \
+       --blank-lines-after-procedures           \
+       --swallow-optional-blank-lines           \
+       --blank-lines-before-block-comments      \
+       --format-all-comments                    \
+       --format-first-column-comments           \
+       --comment-delimiters-on-blank-lines      \
+       --start-left-side-of-comments            \
+       --braces-after-if-line                   \
+       --braces-after-struct-decl-line          \
+       --brace-indent 0                         \
+       --dont-cuddle-else                       \
+       --dont-cuddle-do-while                   \
+       --case-indentation 4                     \
+       --case-brace-indentation 0               \
+       --dont-space-special-semicolon           \
+       --no-space-after-function-call-names     \
+       --no-space-after-casts                   \
+       --no-space-after-for                     \
+       --no-space-after-if                      \
+       --no-space-after-while                   \
+       --space-after-parentheses                \
+       --no-blank-lines-after-commas            \
+       --break-function-decl-args               \
+       --dont-break-function-decl-args-end      \
+       --dont-break-procedure-type              \
+       --indent-level 4                         \
+       --continue-at-parentheses                \
+       "$@"
+

+ 37 - 0
thirdparty/PolarSSL/doxygen/input/doc_encdec.h

@@ -0,0 +1,37 @@
+/**
+ * @file
+ * Encryption/decryption module documentation file.
+ */
+
+/**
+ * @addtogroup encdec_module Encryption/decryption module
+ * 
+ * The Encryption/decryption module provides encryption/decryption functions. 
+ * One can differtiate between symmetric and asymetric algorithms; the 
+ * symmetric ones are mostly used for message confidentiality and the asymmetric 
+ * ones for key exchange and message integrity.
+ * Some symmetric algorithms provide different block cipher modes, mainly 
+ * Electronic Code Book (ECB) which is used for short (64-bit) messages and 
+ * Cipher Block Chaining (CBC) which provides the structure needed for longer 
+ * messages. In addition the Cipher Feedback Mode (CFB-128) stream cipher mode
+ * is implemented for specific algorithms.
+ *
+ * Sometimes the same functions are used for encryption and decryption.
+ * The following algorithms are provided:
+ * - Symmetric:
+ *   - AES (see \c aes_crypt_ecb(), \c aes_crypt_cbc() and \c aes_crypt_cfb128()).
+ *   - ARCFOUR (see \c arc4_crypt()).
+ *   - Camellia (see \c camellia_crypt_ecb(), \c camellia_crypt_cbc() and \c camellia_crypt_cfb128()).
+ *   - DES/3DES (see \c des_crypt_ecb(), \c des_crypt_cbc(), \c des3_crypt_ecb() 
+ *     and \c des3_crypt_cbc()).
+ *   - XTEA (see \c xtea_crypt_ecb()).
+ * - Asymmetric:
+ *   - Diffie-Hellman-Merkle (see \c dhm_read_public(), \c dhm_make_public() 
+ *     and \c dhm_calc_secret()).
+ *   - RSA (see \c rsa_public() and \c rsa_private()).
+ *
+ * This module provides encryption/decryption which can be used to provide 
+ * secrecy.
+ * It also provides asymmetric key functions which can be used for 
+ * confidentiality, integrity, authentication and non-repudiation. 
+ */

+ 20 - 0
thirdparty/PolarSSL/doxygen/input/doc_hashing.h

@@ -0,0 +1,20 @@
+/**
+ * @file
+ * Hashing module documentation file.
+ */
+
+/**
+ * @addtogroup hashing_module Hashing module
+ * 
+ * The Hashing module provides one-way hashing functions. Such functions can be
+ * used for creating a hash message authentication code (HMAC) when sending a 
+ * message. Such a HMAC can be used in combination with a private key
+ * for authentication, which is a message integrity control. 
+ * The following hashing-algorithms are provided:
+ * - MD2, MD4, MD5 128-bit one-way hash functions by Ron Rivest (see 
+ *   \c md2_hmac(), \c md4_hmac() and \c md5_hmac()).
+ * - SHA-1, SHA-256, SHA-384/512 160-bit or more one-way hash functions by 
+ *   NIST and NSA (see\c sha1_hmac(), \c sha2_hmac() and \c sha4_hmac()).
+ *
+ * This module provides one-way hashing which can be used for authentication.
+ */

+ 80 - 0
thirdparty/PolarSSL/doxygen/input/doc_mainpage.h

@@ -0,0 +1,80 @@
+l/**
+ * @file
+ * Main page documentation file.
+ */
+
+/**
+ * @mainpage PolarSSL v1.0.0 source code documentation
+ * 
+ * This documentation describes the internal structure of PolarSSL.  It was
+ * automatically generated from specially formatted comment blocks in
+ * PolarSSL's source code using Doxygen.  (See
+ * http://www.stack.nl/~dimitri/doxygen/ for more information on Doxygen)
+ * 
+ * PolarSSL has a simple setup: it provides the ingredients for an SSL/TLS 
+ * implementation. These ingredients are listed as modules in the 
+ * \ref mainpage_modules "Modules section". This "Modules section" introduces 
+ * the high-level module concepts used throughout this documentation.\n 
+ * Some examples of PolarSSL usage can be found in the \ref mainpage_examples
+ * "Examples section".
+ * 
+ * 
+ * @section mainpage_modules Modules
+ * 
+ * PolarSSL supports SSLv3 up to TLSv1.1 communication by providing the 
+ * following:
+ * - TCP/IP communication functions: listen, connect, accept, read/write.
+ * - SSL/TLS communication functions: init, handshake, read/write.
+ * - X.509 functions: CRT, CRL and key handling
+ * - Random number generation
+ * - Hashing
+ * - Encryption/decryption
+ *
+ * Above functions are split up neatly into logical interfaces. These can be 
+ * used separately to provide any of the above functions or to mix-and-match 
+ * into an SSL server/client solution that utilises a X.509 PKI. Examples of 
+ * such implementations are amply provided with the source code. Note that 
+ * there is also an OpenSSL wrapper provided.\n
+ * Note that PolarSSL does not provide a control channel or (multiple) session
+ * handling. 
+ *
+ * @section mainpage_examples Examples
+ * 
+ * Example server setup:
+ *
+ * \b Prerequisites: 
+ * - X.509 certificate and private key
+ * - session handling functions
+ *
+ * \b Setup:
+ * - Load your certificate and your private RSA key (X.509 interface)
+ * - Setup the listening TCP socket (TCP/IP interface)
+ * - Accept incoming client connection (TCP/IP interface)
+ * - Initialise as an SSL-server (SSL/TLS interface)
+ *   - Set parameters, e.g. authentication, ciphers, CA-chain, key exchange
+ *   - Set callback functions RNG, IO, session handling
+ * - Perform an SSL-handshake (SSL/TLS interface)
+ * - Read/write data (SSL/TLS interface)
+ * - Close and cleanup (all interfaces)
+ *
+ *
+ * Example client setup:
+ *
+ * \b Prerequisites:
+ * - X.509 certificate and private key
+ * - X.509 trusted CA certificates
+ *
+ * \b Setup:
+ * - Load the trusted CA certificates (X.509 interface)
+ * - Load your certificate and your private RSA key (X.509 interface)
+ * - Setup a TCP/IP connection (TCP/IP interface)
+ * - Initialise as an SSL-client (SSL/TLS interface)
+ *   - Set parameters, e.g. authentication mode, ciphers, CA-chain, session
+ *   - Set callback functions RNG, IO
+ * - Perform an SSL-handshake (SSL/TLS interface)
+ * - Verify the server certificate (SSL/TLS interface)
+ * - Write/read data (SSL/TLS interface)
+ * - Close and cleanup (all interfaces)
+ *
+ * 
+ */

+ 18 - 0
thirdparty/PolarSSL/doxygen/input/doc_rng.h

@@ -0,0 +1,18 @@
+/**
+ * @file
+ * Random number generator (RNG) module documentation file.
+ */
+
+/**
+ * @addtogroup rng_module Random number generator (RNG) module
+ * 
+ * The Random number generator (RNG) module provides random number
+ * generation, see \c havege_rand(). It uses the HAVEGE (HArdware Volatile 
+ * Entropy Gathering and Expansion) software heuristic which is claimed 
+ * to be an unpredictable or empirically strong* random number generation.
+ *
+ * \* Meaning that there seems to be no practical algorithm that can guess
+ * the next bit with a probability larger than 1/2 in an output sequence.
+ *
+ * This module can be used to generate random numbers.
+ */

+ 32 - 0
thirdparty/PolarSSL/doxygen/input/doc_ssltls.h

@@ -0,0 +1,32 @@
+/**
+ * @file
+ * SSL/TLS communication module documentation file.
+ */
+
+/**
+ * @addtogroup ssltls_communication_module SSL/TLS communication module
+ * 
+ * The SSL/TLS communication module provides the means to create an SSL/TLS
+ * communication channel. 
+ * The basic provisions are:
+ * - initialise an SSL/TLS context (see \c ssl_init()).
+ * - perform an SSL/TLS handshake (see \c ssl_handshake()).
+ * - read/write (see \c ssl_read() and \c ssl_write()).
+ * - notify a peer that conection is being closed (see \c ssl_close_notify()).
+ *
+ *
+ * Many aspects of such a channel are set through parameters and callback
+ * functions:
+ * - the endpoint role: client or server.
+ * - the authentication mode. Should verification take place.
+ * - the Host-to-host communication channel. A TCP/IP module is provided.
+ * - the random number generator (RNG).
+ * - the ciphers to use for encryption/decryption.
+ * - session control functions.
+ * - X.509 parameters for certificate-handling and key exchange.
+ * 
+ *
+ * This module can be used to create an SSL/TLS server and client and to provide a basic
+ * framework to setup and communicate through an SSL/TLS communication channel.\n
+ * Note that you need to provide for several aspects yourself as mentioned above.
+ */

+ 26 - 0
thirdparty/PolarSSL/doxygen/input/doc_tcpip.h

@@ -0,0 +1,26 @@
+/**
+ * @file
+ * TCP/IP communication module documentation file.
+ */
+
+/**
+ * @addtogroup tcpip_communication_module TCP/IP communication module
+ * 
+ * The TCP/IP communication module provides for a channel of
+ * communication for the \link ssltls_communication_module SSL/TLS communication 
+ * module\endlink to use. 
+ * In the TCP/IP-model it provides for communication up to the Transport 
+ * (or Host-to-host) layer. 
+ * SSL/TLS resides on top of that, in the Application layer, and makes use of
+ * its basic provisions:
+ * - listening on a port (see \c net_bind()).
+ * - accepting a connection (through \c net_accept()).
+ * - read/write (through \c net_recv()/\c net_send()).
+ * - close a connection (through \c net_close()).
+ *
+ * This way you have the means to, for example, implement and use an UDP or 
+ * IPSec communication solution as a basis.
+ * 
+ * This module can be used at server- and clientside to provide a basic
+ * means of communication over the internet.
+ */

+ 21 - 0
thirdparty/PolarSSL/doxygen/input/doc_x509.h

@@ -0,0 +1,21 @@
+/**
+ * @file
+ * X.509 module documentation file.
+ */
+
+/**
+ * @addtogroup x509_module X.509 module
+ * 
+ * The X.509 module provides X.509 support which includes:
+ * - X.509 certificate (CRT) reading (see \c x509parse_crt() and
+ *   \c x509parse_crtfile()).
+ * - X.509 certificate revocation list (CRL) reading (see \c x509parse_crl()
+ *   and\c x509parse_crlfile()).
+ * - X.509 (RSA) private key reading (see \c x509parse_key() and
+ *   \c x509parse_keyfile()).
+ * - X.509 certificate signature verification (see \c x509parse_verify())
+ *
+ * This module can be used to build a certificate authority (CA) chain and
+ * verify its signature. It is also used to get a (RSA) private key for signing
+ * and decryption.
+ */

+ 1575 - 0
thirdparty/PolarSSL/doxygen/polarssl.doxyfile

@@ -0,0 +1,1575 @@
+# Doxyfile 1.6.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "PolarSSL v1.0.0"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = apidoc/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE            =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = .
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = *.c \
+                         *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = tests/fct.h \
+                         programs \
+                         CMakeFiles
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = .
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+#  plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             = WIN32 \
+                         NTLM \
+                         USE_LZO \
+                         ENABLE_FRAGMENT \
+                         P2MP \
+                         P2MP_SERVER \
+                         USE_CRYPTO \
+                         USE_SSL \
+                         ENABLE_PLUGIN \
+                         ENABLE_MANAGEMENT \
+                         ENABLE_OCC \
+                         HAVE_GETTIMEOFDAY
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 1000
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES

+ 5 - 0
thirdparty/PolarSSL/include/CMakeLists.txt

@@ -0,0 +1,5 @@
+FILE(GLOB headers "polarssl/*.h")
+
+INSTALL(FILES ${headers}
+        DESTINATION include/polarssl
+        PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

+ 174 - 0
thirdparty/PolarSSL/include/polarssl/aes.h

@@ -0,0 +1,174 @@
+/**
+ * \file aes.h
+ *
+ * \brief AES block cipher
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Note: This file has been modified by ST's MCD Application Team, to support 
+   the hardware crypto engine embedded in STM32F417xx */
+
+#ifndef POLARSSL_AES_H
+#define POLARSSL_AES_H
+
+#include <string.h>
+
+#define AES_ENCRYPT     1
+#define AES_DECRYPT     0
+
+#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
+#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
+
+/**
+ * \brief          AES context structure
+ */
+typedef struct
+{
+    int nr;                     /*!<  number of rounds  */
+    unsigned long *rk;          /*!<  AES round keys    */
+    unsigned long buf[68];      /*!<  unaligned data    */
+#ifdef USE_STM32F4XX_HW_CRYPTO 
+    unsigned char aes_enc_key[32]; /* Encryption key */
+    unsigned char aes_dec_key[32]; /* Decryption key */
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+}aes_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          AES key schedule (encryption)
+ *
+ * \param ctx      AES context to be initialized
+ * \param key      encryption key
+ * \param keysize  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief          AES key schedule (decryption)
+ *
+ * \param ctx      AES context to be initialized
+ * \param key      decryption key
+ * \param keysize  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief          AES-ECB block encryption/decryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 if successful
+ */
+int aes_crypt_ecb( aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+/**
+ * \brief          AES-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (16 bytes)
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
+ */
+int aes_crypt_cbc( aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+
+/**
+ * \brief          AES-CFB128 buffer encryption/decryption.
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param length   length of the input data
+ * \param iv_off   offset in IV (updated after use)
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/*
+ * \brief               AES-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * \param length        The length of the data
+ * \param nc_off        The offset in the current stream_block (for resuming
+ *                      within current cipher stream). The offset pointer to
+ *                      should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block  The saved stream-block for resuming. Is overwritten
+ *                      by the function.
+ * \param input         The input data stream
+ * \param output        The output data stream
+ *
+ * \return         0 if successful
+ */
+int aes_crypt_ctr( aes_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */

+ 80 - 0
thirdparty/PolarSSL/include/polarssl/arc4.h

@@ -0,0 +1,80 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ARC4_H
+#define POLARSSL_ARC4_H
+
+#include <string.h>
+
+/**
+ * \brief          ARC4 context structure
+ */
+typedef struct
+{
+    int x;                      /*!< permutation index */
+    int y;                      /*!< permutation index */
+    unsigned char m[256];       /*!< permutation table */
+}
+arc4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          ARC4 key schedule
+ *
+ * \param ctx      ARC4 context to be initialized
+ * \param key      the secret key
+ * \param keylen   length of the key
+ */
+void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen );
+
+/**
+ * \brief          ARC4 cipher function
+ *
+ * \param ctx      ARC4 context
+ * \param length   length of the input data
+ * \param input    buffer holding the input data
+ * \param output   buffer for the output data
+ *
+ * \return         0 if successful
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+                unsigned char *output );
+
+/*
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int arc4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* arc4.h */

+ 87 - 0
thirdparty/PolarSSL/include/polarssl/base64.h

@@ -0,0 +1,87 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BASE64_H
+#define POLARSSL_BASE64_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL               -0x0010  /**< Output buffer too small. */
+#define POLARSSL_ERR_BASE64_INVALID_CHARACTER              -0x0012  /**< Invalid character in input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Encode a buffer into base64 format
+ *
+ * \param dst      destination buffer
+ * \param dlen     size of the buffer
+ * \param src      source buffer
+ * \param slen     amount of data to be encoded
+ *
+ * \return         0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
+ *                 *dlen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *dlen = 0 to obtain the
+ *                 required buffer size in *dlen
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Decode a base64-formatted buffer
+ *
+ * \param dst      destination buffer
+ * \param dlen     size of the buffer
+ * \param src      source buffer
+ * \param slen     amount of data to be decoded
+ *
+ * \return         0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
+ *                 POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not
+ *                 correct. *dlen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *dlen = 0 to obtain the
+ *                 required buffer size in *dlen
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */

+ 592 - 0
thirdparty/PolarSSL/include/polarssl/bignum.h

@@ -0,0 +1,592 @@
+/**
+ * \file bignum.h
+ *
+ * \brief  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BIGNUM_H
+#define POLARSSL_BIGNUM_H
+
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#include <string.h>
+
+#define POLARSSL_ERR_MPI_FILE_IO_ERROR                     -0x0002  /**< An error occurred while reading from or writing to a file. */
+#define POLARSSL_ERR_MPI_BAD_INPUT_DATA                    -0x0004  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MPI_INVALID_CHARACTER                 -0x0006  /**< There is an invalid character in the digit string. */
+#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL                  -0x0008  /**< The output buffer is too small to write too. */
+#define POLARSSL_ERR_MPI_NEGATIVE_VALUE                    -0x000A  /**< The input arguments are negative or result in illegal output. */
+#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO                  -0x000C  /**< The input argument for division is zero, which is not allowed. */
+#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE                    -0x000E  /**< The input arguments are not acceptable. */
+
+#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
+
+/*
+ * Maximum size MPIs are allowed to grow to in number of limbs.
+ */
+#define POLARSSL_MPI_MAX_LIMBS                             10000
+
+/*
+ * Define the base integer type, architecture-wise
+ */
+#if defined(POLARSSL_HAVE_INT8)
+typedef   signed char  t_sint;
+typedef unsigned char  t_uint;
+typedef unsigned short t_udbl;
+#else
+#if defined(POLARSSL_HAVE_INT16)
+typedef   signed short t_sint;
+typedef unsigned short t_uint;
+typedef unsigned long  t_udbl;
+#else
+  typedef   signed long t_sint;
+  typedef unsigned long t_uint;
+  #if defined(_MSC_VER) && defined(_M_IX86)
+  typedef unsigned __int64 t_udbl;
+  #else
+    #if defined(__amd64__) || defined(__x86_64__)    || \
+        defined(__ppc64__) || defined(__powerpc64__) || \
+        defined(__ia64__)  || defined(__alpha__)
+    typedef unsigned int t_udbl __attribute__((mode(TI)));
+    #else
+      #if defined(POLARSSL_HAVE_LONGLONG)
+      typedef unsigned long long t_udbl;
+      #endif
+    #endif
+  #endif
+#endif
+#endif
+
+/**
+ * \brief          MPI structure
+ */
+typedef struct
+{
+    int s;              /*!<  integer sign      */
+    size_t n;           /*!<  total # of limbs  */
+    t_uint *p;          /*!<  pointer to limbs  */
+}
+mpi;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief           Initialize one MPI
+ *
+ * \param X         One MPI to initialize.
+ */
+void mpi_init( mpi *X );
+
+/**
+ * \brief          Unallocate one MPI
+ *
+ * \param X        One MPI to unallocate.
+ */
+void mpi_free( mpi *X );
+
+/**
+ * \brief          Enlarge to the specified number of limbs
+ *
+ * \param X        MPI to grow
+ * \param nblimbs  The target number of limbs
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_grow( mpi *X, size_t nblimbs );
+
+/**
+ * \brief          Copy the contents of Y into X
+ *
+ * \param X        Destination MPI
+ * \param Y        Source MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_copy( mpi *X, const mpi *Y );
+
+/**
+ * \brief          Swap the contents of X and Y
+ *
+ * \param X        First MPI value
+ * \param Y        Second MPI value
+ */
+void mpi_swap( mpi *X, mpi *Y );
+
+/**
+ * \brief          Set value from integer
+ *
+ * \param X        MPI to set
+ * \param z        Value to use
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_lset( mpi *X, t_sint z );
+
+/*
+ * \brief          Get a specific bit from X
+ *
+ * \param X        MPI to use
+ * \param pos      Zero-based index of the bit in X
+ *
+ * \return         Either a 0 or a 1
+ */
+int mpi_get_bit( mpi *X, size_t pos );
+
+/*
+ * \brief          Set a bit of X to a specific value of 0 or 1
+ *
+ * \note           Will grow X if necessary to set a bit to 1 in a not yet
+ *                 existing limb. Will not grow if bit should be set to 0
+ *
+ * \param X        MPI to use
+ * \param pos      Zero-based index of the bit in X
+ * \param val      The value to set the bit to (0 or 1)
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val );
+
+/**
+ * \brief          Return the number of least significant bits
+ *
+ * \param X        MPI to use
+ */
+size_t mpi_lsb( const mpi *X );
+
+/**
+ * \brief          Return the number of most significant bits
+ *
+ * \param X        MPI to use
+ */
+size_t mpi_msb( const mpi *X );
+
+/**
+ * \brief          Return the total size in bytes
+ *
+ * \param X        MPI to use
+ */
+size_t mpi_size( const mpi *X );
+
+/**
+ * \brief          Import from an ASCII string
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param s        Null-terminated string buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_string( mpi *X, int radix, const char *s );
+
+/**
+ * \brief          Export into an ASCII string
+ *
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param s        String buffer
+ * \param slen     String buffer size
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code.
+ *                 *slen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *slen = 0 to obtain the
+ *                 minimum required buffer size in *slen.
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );
+
+/**
+ * \brief          Read X from an opened file
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param fin      Input file handle
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+//int mpi_read_file( mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief          Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p        Prefix, can be NULL
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param fout     Output file handle (can be NULL)
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note           Set fout == NULL to print X on the console.
+ */
+//int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
+
+/**
+ * \brief          Import X from unsigned binary data, big endian
+ *
+ * \param X        Destination MPI
+ * \param buf      Input buffer
+ * \param buflen   Input buffer size
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Export X into unsigned binary data, big endian
+ *
+ * \param X        Source MPI
+ * \param buf      Output buffer
+ * \param buflen   Output buffer size
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Left-shift: X <<= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_shift_l( mpi *X, size_t count );
+
+/**
+ * \brief          Right-shift: X >>= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_shift_r( mpi *X, size_t count );
+
+/**
+ * \brief          Compare unsigned values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if |X| is greater than |Y|,
+ *                -1 if |X| is lesser  than |Y| or
+ *                 0 if |X| is equal to |Y|
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if X is greater than Y,
+ *                -1 if X is lesser  than Y or
+ *                 0 if X is equal to Y
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param z        The integer value to compare to
+ *
+ * \return         1 if X is greater than z,
+ *                -1 if X is lesser  than z or
+ *                 0 if X is equal to z
+ */
+int mpi_cmp_int( const mpi *X, t_sint z );
+
+/**
+ * \brief          Unsigned addition: X = |A| + |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Unsigned substraction: X = |A| - |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Signed substraction: X = A - B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to add
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief          Signed substraction: X = A - b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to subtract
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief          Baseline multiplication: X = A * B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Baseline multiplication: X = A * b
+ *                 Note: b is an unsigned integer type, thus
+ *                 Negative values of b are ignored.
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to multiply with
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief          Division by mpi: A = Q * B + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Division by int: A = Q * b + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b );
+
+/**
+ * \brief          Modulo: R = A mod B
+ *
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Modulo: r = A mod b
+ *
+ * \param r        Destination t_uint
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
+
+/**
+ * \brief          Sliding-window exponentiation: X = A^E mod N
+ *
+ * \param X        Destination MPI 
+ * \param A        Left-hand MPI
+ * \param E        Exponent MPI
+ * \param N        Modular MPI
+ * \param _RR      Speed-up MPI used for recalculations
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
+ *
+ * \note           _RR is used to avoid re-computing R*R mod N across
+ *                 multiple calls, which speeds up things a bit. It can
+ *                 be set to NULL if the extra performance is unneeded.
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
+
+/**
+ * \brief          Fill an MPI X with size bytes of random
+ *
+ * \param X        Destination MPI
+ * \param size     Size in bytes
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_fill_random( mpi *X, size_t size, int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief          Greatest common divisor: G = gcd(A, B)
+ *
+ * \param G        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Modular inverse: X = A^-1 mod N
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param N        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
+                   POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
+
+/**
+ * \brief          Miller-Rabin primality test
+ *
+ * \param X        MPI to check
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful (probably prime),
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief          Prime number generation
+ *
+ * \param X        Destination MPI
+ * \param nbits    Required size of X in bits ( 3 <= nbits <= 4096 )
+ * \param dh_flag  If 1, then (X-1)/2 will be prime too
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful (probably prime),
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+                   int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */

+ 738 - 0
thirdparty/PolarSSL/include/polarssl/bn_mul.h

@@ -0,0 +1,738 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *      Multiply source vector [s] with b, add result
+ *       to destination vector [d] and set carry c.
+ *
+ *      Currently supports:
+ *
+ *         . IA-32 (386+)         . AMD64 / EM64T
+ *         . IA-32 (SSE2)         . Motorola 68000
+ *         . PowerPC, 32-bit      . MicroBlaze
+ *         . PowerPC, 64-bit      . TriCore
+ *         . SPARC v8             . ARM v3+
+ *         . Alpha                . MIPS32
+ *         . C, longlong          . C, generic
+ */
+#ifndef POLARSSL_BN_MUL_H
+#define POLARSSL_BN_MUL_H
+
+#include "config.h"
+
+#if defined(POLARSSL_HAVE_ASM)
+
+#if defined(__GNUC__)
+#if defined(__i386__)
+
+#define MULADDC_INIT                \
+    asm( "                          \
+        movl   %%ebx, %0;           \
+        movl   %5, %%esi;           \
+        movl   %6, %%edi;           \
+        movl   %7, %%ecx;           \
+        movl   %8, %%ebx;           \
+        "
+
+#define MULADDC_CORE                \
+        "                           \
+        lodsl;                      \
+        mull   %%ebx;               \
+        addl   %%ecx,   %%eax;      \
+        adcl   $0,      %%edx;      \
+        addl   (%%edi), %%eax;      \
+        adcl   $0,      %%edx;      \
+        movl   %%edx,   %%ecx;      \
+        stosl;                      \
+        "
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT                    \
+        "                               \
+        movd     %%ecx,     %%mm1;      \
+        movd     %%ebx,     %%mm0;      \
+        movd     (%%edi),   %%mm3;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     (%%esi),   %%mm2;      \
+        pmuludq  %%mm0,     %%mm2;      \
+        movd     4(%%esi),  %%mm4;      \
+        pmuludq  %%mm0,     %%mm4;      \
+        movd     8(%%esi),  %%mm6;      \
+        pmuludq  %%mm0,     %%mm6;      \
+        movd     12(%%esi), %%mm7;      \
+        pmuludq  %%mm0,     %%mm7;      \
+        paddq    %%mm2,     %%mm1;      \
+        movd     4(%%edi),  %%mm3;      \
+        paddq    %%mm4,     %%mm3;      \
+        movd     8(%%edi),  %%mm5;      \
+        paddq    %%mm6,     %%mm5;      \
+        movd     12(%%edi), %%mm4;      \
+        paddq    %%mm4,     %%mm7;      \
+        movd     %%mm1,     (%%edi);    \
+        movd     16(%%esi), %%mm2;      \
+        pmuludq  %%mm0,     %%mm2;      \
+        psrlq    $32,       %%mm1;      \
+        movd     20(%%esi), %%mm4;      \
+        pmuludq  %%mm0,     %%mm4;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     24(%%esi), %%mm6;      \
+        pmuludq  %%mm0,     %%mm6;      \
+        movd     %%mm1,     4(%%edi);   \
+        psrlq    $32,       %%mm1;      \
+        movd     28(%%esi), %%mm3;      \
+        pmuludq  %%mm0,     %%mm3;      \
+        paddq    %%mm5,     %%mm1;      \
+        movd     16(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm2;      \
+        movd     %%mm1,     8(%%edi);   \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm7,     %%mm1;      \
+        movd     20(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm4;      \
+        movd     %%mm1,     12(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm2,     %%mm1;      \
+        movd     24(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm6;      \
+        movd     %%mm1,     16(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm4,     %%mm1;      \
+        movd     28(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm3;      \
+        movd     %%mm1,     20(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm6,     %%mm1;      \
+        movd     %%mm1,     24(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     %%mm1,     28(%%edi);  \
+        addl     $32,       %%edi;      \
+        addl     $32,       %%esi;      \
+        psrlq    $32,       %%mm1;      \
+        movd     %%mm1,     %%ecx;      \
+        "
+
+#define MULADDC_STOP            \
+        "                       \
+        emms;                   \
+        movl   %4, %%ebx;       \
+        movl   %%ecx, %1;       \
+        movl   %%edi, %2;       \
+        movl   %%esi, %3;       \
+        "                       \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+
+#else
+
+#define MULADDC_STOP            \
+        "                       \
+        movl   %4, %%ebx;       \
+        movl   %%ecx, %1;       \
+        movl   %%edi, %2;       \
+        movl   %%esi, %3;       \
+        "                       \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT                            \
+    asm( "movq   %0, %%rsi      " :: "m" (s));  \
+    asm( "movq   %0, %%rdi      " :: "m" (d));  \
+    asm( "movq   %0, %%rcx      " :: "m" (c));  \
+    asm( "movq   %0, %%rbx      " :: "m" (b));  \
+    asm( "xorq   %r8, %r8       " );
+
+#define MULADDC_CORE                            \
+    asm( "movq  (%rsi),%rax     " );            \
+    asm( "mulq   %rbx           " );            \
+    asm( "addq   $8,   %rsi     " );            \
+    asm( "addq   %rcx, %rax     " );            \
+    asm( "movq   %r8,  %rcx     " );            \
+    asm( "adcq   $0,   %rdx     " );            \
+    asm( "nop                   " );            \
+    asm( "addq   %rax, (%rdi)   " );            \
+    asm( "adcq   %rdx, %rcx     " );            \
+    asm( "addq   $8,   %rdi     " );
+
+#define MULADDC_STOP                            \
+    asm( "movq   %%rcx, %0      " : "=m" (c));  \
+    asm( "movq   %%rdi, %0      " : "=m" (d));  \
+    asm( "movq   %%rsi, %0      " : "=m" (s) :: \
+    "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT                            \
+    asm( "movl   %0, %%a2       " :: "m" (s));  \
+    asm( "movl   %0, %%a3       " :: "m" (d));  \
+    asm( "movl   %0, %%d3       " :: "m" (c));  \
+    asm( "movl   %0, %%d2       " :: "m" (b));  \
+    asm( "moveq  #0, %d0        " );
+
+#define MULADDC_CORE                            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addl   %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "moveq  #0,  %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "addxl  %d4, %d3       " );
+
+#define MULADDC_STOP                            \
+    asm( "movl   %%d3, %0       " : "=m" (c));  \
+    asm( "movl   %%a3, %0       " : "=m" (d));  \
+    asm( "movl   %%a2, %0       " : "=m" (s) :: \
+    "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
+
+#define MULADDC_HUIT                            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "addxl  %d0, %d3       " );
+
+#endif /* MC68000 */
+
+#if defined(__powerpc__)   || defined(__ppc__)
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                            \
+    asm( "ld     r3, %0         " :: "m" (s));  \
+    asm( "ld     r4, %0         " :: "m" (d));  \
+    asm( "ld     r5, %0         " :: "m" (c));  \
+    asm( "ld     r6, %0         " :: "m" (b));  \
+    asm( "addi   r3, r3, -8     " );            \
+    asm( "addi   r4, r4, -8     " );            \
+    asm( "addic  r5, r5,  0     " );
+
+#define MULADDC_CORE                            \
+    asm( "ldu    r7, 8(r3)      " );            \
+    asm( "mulld  r8, r7, r6     " );            \
+    asm( "mulhdu r9, r7, r6     " );            \
+    asm( "adde   r8, r8, r5     " );            \
+    asm( "ld     r7, 8(r4)      " );            \
+    asm( "addze  r5, r9         " );            \
+    asm( "addc   r8, r8, r7     " );            \
+    asm( "stdu   r8, 8(r4)      " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  r5, r5         " );            \
+    asm( "addi   r4, r4, 8      " );            \
+    asm( "addi   r3, r3, 8      " );            \
+    asm( "std    r5, %0         " : "=m" (c));  \
+    asm( "std    r4, %0         " : "=m" (d));  \
+    asm( "std    r3, %0         " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT                            \
+    asm( "ld     %%r3, %0       " :: "m" (s));  \
+    asm( "ld     %%r4, %0       " :: "m" (d));  \
+    asm( "ld     %%r5, %0       " :: "m" (c));  \
+    asm( "ld     %%r6, %0       " :: "m" (b));  \
+    asm( "addi   %r3, %r3, -8   " );            \
+    asm( "addi   %r4, %r4, -8   " );            \
+    asm( "addic  %r5, %r5,  0   " );
+
+#define MULADDC_CORE                            \
+    asm( "ldu    %r7, 8(%r3)    " );            \
+    asm( "mulld  %r8, %r7, %r6  " );            \
+    asm( "mulhdu %r9, %r7, %r6  " );            \
+    asm( "adde   %r8, %r8, %r5  " );            \
+    asm( "ld     %r7, 8(%r4)    " );            \
+    asm( "addze  %r5, %r9       " );            \
+    asm( "addc   %r8, %r8, %r7  " );            \
+    asm( "stdu   %r8, 8(%r4)    " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  %r5, %r5       " );            \
+    asm( "addi   %r4, %r4, 8    " );            \
+    asm( "addi   %r3, %r3, 8    " );            \
+    asm( "std    %%r5, %0       " : "=m" (c));  \
+    asm( "std    %%r4, %0       " : "=m" (d));  \
+    asm( "std    %%r3, %0       " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#else /* PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                            \
+    asm( "lwz    r3, %0         " :: "m" (s));  \
+    asm( "lwz    r4, %0         " :: "m" (d));  \
+    asm( "lwz    r5, %0         " :: "m" (c));  \
+    asm( "lwz    r6, %0         " :: "m" (b));  \
+    asm( "addi   r3, r3, -4     " );            \
+    asm( "addi   r4, r4, -4     " );            \
+    asm( "addic  r5, r5,  0     " );
+
+#define MULADDC_CORE                            \
+    asm( "lwzu   r7, 4(r3)      " );            \
+    asm( "mullw  r8, r7, r6     " );            \
+    asm( "mulhwu r9, r7, r6     " );            \
+    asm( "adde   r8, r8, r5     " );            \
+    asm( "lwz    r7, 4(r4)      " );            \
+    asm( "addze  r5, r9         " );            \
+    asm( "addc   r8, r8, r7     " );            \
+    asm( "stwu   r8, 4(r4)      " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  r5, r5         " );            \
+    asm( "addi   r4, r4, 4      " );            \
+    asm( "addi   r3, r3, 4      " );            \
+    asm( "stw    r5, %0         " : "=m" (c));  \
+    asm( "stw    r4, %0         " : "=m" (d));  \
+    asm( "stw    r3, %0         " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT                            \
+    asm( "lwz    %%r3, %0       " :: "m" (s));  \
+    asm( "lwz    %%r4, %0       " :: "m" (d));  \
+    asm( "lwz    %%r5, %0       " :: "m" (c));  \
+    asm( "lwz    %%r6, %0       " :: "m" (b));  \
+    asm( "addi   %r3, %r3, -4   " );            \
+    asm( "addi   %r4, %r4, -4   " );            \
+    asm( "addic  %r5, %r5,  0   " );
+
+#define MULADDC_CORE                            \
+    asm( "lwzu   %r7, 4(%r3)    " );            \
+    asm( "mullw  %r8, %r7, %r6  " );            \
+    asm( "mulhwu %r9, %r7, %r6  " );            \
+    asm( "adde   %r8, %r8, %r5  " );            \
+    asm( "lwz    %r7, 4(%r4)    " );            \
+    asm( "addze  %r5, %r9       " );            \
+    asm( "addc   %r8, %r8, %r7  " );            \
+    asm( "stwu   %r8, 4(%r4)    " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  %r5, %r5       " );            \
+    asm( "addi   %r4, %r4, 4    " );            \
+    asm( "addi   %r3, %r3, 4    " );            \
+    asm( "stw    %%r5, %0       " : "=m" (c));  \
+    asm( "stw    %%r4, %0       " : "=m" (d));  \
+    asm( "stw    %%r3, %0       " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#endif /* PPC32 */
+#endif /* PPC64 */
+
+#if defined(__sparc__)
+
+#define MULADDC_INIT                            \
+    asm( "ld     %0, %%o0       " :: "m" (s));  \
+    asm( "ld     %0, %%o1       " :: "m" (d));  \
+    asm( "ld     %0, %%o2       " :: "m" (c));  \
+    asm( "ld     %0, %%o3       " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "ld    [%o0], %o4      " );            \
+    asm( "inc      4,  %o0      " );            \
+    asm( "ld    [%o1], %o5      " );            \
+    asm( "umul   %o3,  %o4, %o4 " );            \
+    asm( "addcc  %o4,  %o2, %o4 " );            \
+    asm( "rd      %y,  %g1      " );            \
+    asm( "addx   %g1,    0, %g1 " );            \
+    asm( "addcc  %o4,  %o5, %o4 " );            \
+    asm( "st     %o4, [%o1]     " );            \
+    asm( "addx   %g1,    0, %o2 " );            \
+    asm( "inc      4,  %o1      " );
+
+#define MULADDC_STOP                            \
+    asm( "st     %%o2, %0       " : "=m" (c));  \
+    asm( "st     %%o1, %0       " : "=m" (d));  \
+    asm( "st     %%o0, %0       " : "=m" (s) :: \
+    "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT                            \
+    asm( "lwi   r3,   %0        " :: "m" (s));  \
+    asm( "lwi   r4,   %0        " :: "m" (d));  \
+    asm( "lwi   r5,   %0        " :: "m" (c));  \
+    asm( "lwi   r6,   %0        " :: "m" (b));  \
+    asm( "andi  r7,   r6, 0xffff" );            \
+    asm( "bsrli r6,   r6, 16    " );
+
+#define MULADDC_CORE                            \
+    asm( "lhui  r8,   r3,   0   " );            \
+    asm( "addi  r3,   r3,   2   " );            \
+    asm( "lhui  r9,   r3,   0   " );            \
+    asm( "addi  r3,   r3,   2   " );            \
+    asm( "mul   r10,  r9,  r6   " );            \
+    asm( "mul   r11,  r8,  r7   " );            \
+    asm( "mul   r12,  r9,  r7   " );            \
+    asm( "mul   r13,  r8,  r6   " );            \
+    asm( "bsrli  r8, r10,  16   " );            \
+    asm( "bsrli  r9, r11,  16   " );            \
+    asm( "add   r13, r13,  r8   " );            \
+    asm( "add   r13, r13,  r9   " );            \
+    asm( "bslli r10, r10,  16   " );            \
+    asm( "bslli r11, r11,  16   " );            \
+    asm( "add   r12, r12, r10   " );            \
+    asm( "addc  r13, r13,  r0   " );            \
+    asm( "add   r12, r12, r11   " );            \
+    asm( "addc  r13, r13,  r0   " );            \
+    asm( "lwi   r10,  r4,   0   " );            \
+    asm( "add   r12, r12, r10   " );            \
+    asm( "addc  r13, r13,  r0   " );            \
+    asm( "add   r12, r12,  r5   " );            \
+    asm( "addc   r5, r13,  r0   " );            \
+    asm( "swi   r12,  r4,   0   " );            \
+    asm( "addi   r4,  r4,   4   " );
+
+#define MULADDC_STOP                            \
+    asm( "swi   r5,   %0        " : "=m" (c));  \
+    asm( "swi   r4,   %0        " : "=m" (d));  \
+    asm( "swi   r3,   %0        " : "=m" (s) :: \
+     "r3", "r4" , "r5" , "r6" , "r7" , "r8" ,   \
+     "r9", "r10", "r11", "r12", "r13" );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT                            \
+    asm( "ld.a   %%a2, %0       " :: "m" (s));  \
+    asm( "ld.a   %%a3, %0       " :: "m" (d));  \
+    asm( "ld.w   %%d4, %0       " :: "m" (c));  \
+    asm( "ld.w   %%d1, %0       " :: "m" (b));  \
+    asm( "xor    %d5, %d5       " );
+
+#define MULADDC_CORE                            \
+    asm( "ld.w   %d0,   [%a2+]      " );        \
+    asm( "madd.u %e2, %e4, %d0, %d1 " );        \
+    asm( "ld.w   %d0,   [%a3]       " );        \
+    asm( "addx   %d2,    %d2,  %d0  " );        \
+    asm( "addc   %d3,    %d3,    0  " );        \
+    asm( "mov    %d4,    %d3        " );        \
+    asm( "st.w  [%a3+],  %d2        " );
+
+#define MULADDC_STOP                            \
+    asm( "st.w   %0, %%d4       " : "=m" (c));  \
+    asm( "st.a   %0, %%a3       " : "=m" (d));  \
+    asm( "st.a   %0, %%a2       " : "=m" (s) :: \
+    "d0", "d1", "e2", "d4", "a2", "a3" );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#define MULADDC_INIT                            \
+    asm( "ldr    r0, %0         " :: "m" (s));  \
+    asm( "ldr    r1, %0         " :: "m" (d));  \
+    asm( "ldr    r2, %0         " :: "m" (c));  \
+    asm( "ldr    r3, %0         " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "ldr    r4, [r0], #4   " );            \
+    asm( "mov    r5, #0         " );            \
+    asm( "ldr    r6, [r1]       " );            \
+    asm( "umlal  r2, r5, r3, r4 " );            \
+    asm( "adds   r7, r6, r2     " );            \
+    asm( "adc    r2, r5, #0     " );            \
+    asm( "str    r7, [r1], #4   " );
+
+#define MULADDC_STOP                            \
+    asm( "str    r2, %0         " : "=m" (c));  \
+    asm( "str    r1, %0         " : "=m" (d));  \
+    asm( "str    r0, %0         " : "=m" (s) :: \
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT                            \
+    asm( "ldq    $1, %0         " :: "m" (s));  \
+    asm( "ldq    $2, %0         " :: "m" (d));  \
+    asm( "ldq    $3, %0         " :: "m" (c));  \
+    asm( "ldq    $4, %0         " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "ldq    $6,  0($1)     " );            \
+    asm( "addq   $1,  8, $1     " );            \
+    asm( "mulq   $6, $4, $7     " );            \
+    asm( "umulh  $6, $4, $6     " );            \
+    asm( "addq   $7, $3, $7     " );            \
+    asm( "cmpult $7, $3, $3     " );            \
+    asm( "ldq    $5,  0($2)     " );            \
+    asm( "addq   $7, $5, $7     " );            \
+    asm( "cmpult $7, $5, $5     " );            \
+    asm( "stq    $7,  0($2)     " );            \
+    asm( "addq   $2,  8, $2     " );            \
+    asm( "addq   $6, $3, $3     " );            \
+    asm( "addq   $5, $3, $3     " );
+
+#define MULADDC_STOP                            \
+    asm( "stq    $3, %0         " : "=m" (c));  \
+    asm( "stq    $2, %0         " : "=m" (d));  \
+    asm( "stq    $1, %0         " : "=m" (s) :: \
+    "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
+
+#endif /* Alpha */
+
+#if defined(__mips__)
+
+#define MULADDC_INIT                            \
+    asm( "lw     $10, %0        " :: "m" (s));  \
+    asm( "lw     $11, %0        " :: "m" (d));  \
+    asm( "lw     $12, %0        " :: "m" (c));  \
+    asm( "lw     $13, %0        " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "lw     $14, 0($10)    " );            \
+    asm( "multu  $13, $14       " );            \
+    asm( "addi   $10, $10, 4    " );            \
+    asm( "mflo   $14            " );            \
+    asm( "mfhi   $9             " );            \
+    asm( "addu   $14, $12, $14  " );            \
+    asm( "lw     $15, 0($11)    " );            \
+    asm( "sltu   $12, $14, $12  " );            \
+    asm( "addu   $15, $14, $15  " );            \
+    asm( "sltu   $14, $15, $14  " );            \
+    asm( "addu   $12, $12, $9   " );            \
+    asm( "sw     $15, 0($11)    " );            \
+    asm( "addu   $12, $12, $14  " );            \
+    asm( "addi   $11, $11, 4    " );
+
+#define MULADDC_STOP                            \
+    asm( "sw     $12, %0        " : "=m" (c));  \
+    asm( "sw     $11, %0        " : "=m" (d));  \
+    asm( "sw     $10, %0        " : "=m" (s) :: \
+    "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT                            \
+    __asm   mov     esi, s                      \
+    __asm   mov     edi, d                      \
+    __asm   mov     ecx, c                      \
+    __asm   mov     ebx, b
+
+#define MULADDC_CORE                            \
+    __asm   lodsd                               \
+    __asm   mul     ebx                         \
+    __asm   add     eax, ecx                    \
+    __asm   adc     edx, 0                      \
+    __asm   add     eax, [edi]                  \
+    __asm   adc     edx, 0                      \
+    __asm   mov     ecx, edx                    \
+    __asm   stosd
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_HUIT                            \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
+    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
+    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
+
+#define MULADDC_STOP                            \
+    EMIT 0x0F  EMIT 0x77                        \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi                      \
+
+#else
+
+#define MULADDC_STOP                            \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi                      \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* POLARSSL_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(POLARSSL_HAVE_LONGLONG)
+
+#define MULADDC_INIT                    \
+{                                       \
+    t_udbl r;                           \
+    t_uint r0, r1;
+
+#define MULADDC_CORE                    \
+    r   = *(s++) * (t_udbl) b;           \
+    r0  = r;                            \
+    r1  = r >> biL;                     \
+    r0 += c;  r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_STOP                    \
+}
+
+#else
+#define MULADDC_INIT                    \
+{                                       \
+    t_uint s0, s1, b0, b1;              \
+    t_uint r0, r1, rx, ry;              \
+    b0 = ( b << biH ) >> biH;           \
+    b1 = ( b >> biH );
+
+#define MULADDC_CORE                    \
+    s0 = ( *s << biH ) >> biH;          \
+    s1 = ( *s >> biH ); s++;            \
+    rx = s0 * b1; r0 = s0 * b0;         \
+    ry = s1 * b0; r1 = s1 * b1;         \
+    r1 += ( rx >> biH );                \
+    r1 += ( ry >> biH );                \
+    rx <<= biH; ry <<= biH;             \
+    r0 += rx; r1 += (r0 < rx);          \
+    r0 += ry; r1 += (r0 < ry);          \
+    r0 +=  c; r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_STOP                    \
+}
+
+#endif /* C (generic)  */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */

+ 174 - 0
thirdparty/PolarSSL/include/polarssl/camellia.h

@@ -0,0 +1,174 @@
+/**
+ * \file camellia.h
+ *
+ * \brief Camellia block cipher
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CAMELLIA_H
+#define POLARSSL_CAMELLIA_H
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define CAMELLIA_ENCRYPT     1
+#define CAMELLIA_DECRYPT     0
+
+#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH           -0x0024  /**< Invalid key length. */
+#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH         -0x0026  /**< Invalid data input length. */
+
+/**
+ * \brief          CAMELLIA context structure
+ */
+typedef struct
+{
+    int nr;                     /*!<  number of rounds  */
+    uint32_t rk[68];            /*!<  CAMELLIA round keys    */
+}
+camellia_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          CAMELLIA key schedule (encryption)
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ * \param key      encryption key
+ * \param keysize  must be 128, 192 or 256
+ * 
+ * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief          CAMELLIA key schedule (decryption)
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ * \param key      decryption key
+ * \param keysize  must be 128, 192 or 256
+ * 
+ * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief          CAMELLIA-ECB block encryption/decryption
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ * 
+ * \return         0 if successful
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+/**
+ * \brief          CAMELLIA-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (16 bytes)
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ * 
+ * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+
+/**
+ * \brief          CAMELLIA-CFB128 buffer encryption/decryption
+ *
+ * \param ctx      CAMELLIA context
+ * \param mode     CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param length   length of the input data
+ * \param iv_off   offset in IV (updated after use)
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ * 
+ * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/*
+ * \brief               CAMELLIA-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * \param length        The length of the data
+ * \param nc_off        The offset in the current stream_block (for resuming
+ *                      within current cipher stream). The offset pointer to
+ *                      should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block  The saved stream-block for resuming. Is overwritten
+ *                      by the function.
+ * \param input         The input data stream
+ * \param output        The output data stream
+ *
+ * \return         0 if successful
+ */
+int camellia_crypt_ctr( camellia_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int camellia_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* camellia.h */

+ 47 - 0
thirdparty/PolarSSL/include/polarssl/certs.h

@@ -0,0 +1,47 @@
+/**
+ * \file certs.h
+ *
+ * \brief Sample certificates and DHM parameters for testing
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CERTS_H
+#define POLARSSL_CERTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char test_ca_crt[];
+extern const char test_ca_key[];
+extern const char test_ca_pwd[];
+extern const char test_srv_crt[];
+extern const char test_srv_key[];
+extern const char test_cli_crt[];
+extern const char test_cli_key[];
+extern const char test_dhm_params[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* certs.h */

+ 420 - 0
thirdparty/PolarSSL/include/polarssl/cipher.h

@@ -0,0 +1,420 @@
+/**
+ * \file cipher.h
+ * 
+ * \brief Generic cipher wrapper.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_CIPHER_H
+#define POLARSSL_CIPHER_H
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE            -0x6080  /**< The selected feature is not available. */
+#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA                 -0x6100  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_CIPHER_ALLOC_FAILED                   -0x6180  /**< Failed to allocate memory. */
+#define POLARSSL_ERR_CIPHER_INVALID_PADDING                -0x6200  /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED            -0x6280  /**< Decryption of block requires a full block. */
+
+typedef enum {
+    POLARSSL_CIPHER_ID_NONE = 0,
+    POLARSSL_CIPHER_ID_AES,
+    POLARSSL_CIPHER_ID_DES,
+    POLARSSL_CIPHER_ID_3DES,
+    POLARSSL_CIPHER_ID_CAMELLIA,
+} cipher_id_t;
+
+typedef enum {
+    POLARSSL_CIPHER_NONE = 0,
+    POLARSSL_CIPHER_AES_128_CBC,
+    POLARSSL_CIPHER_AES_192_CBC,
+    POLARSSL_CIPHER_AES_256_CBC,
+    POLARSSL_CIPHER_AES_128_CFB128,
+    POLARSSL_CIPHER_AES_192_CFB128,
+    POLARSSL_CIPHER_AES_256_CFB128,
+    POLARSSL_CIPHER_AES_128_CTR,
+    POLARSSL_CIPHER_AES_192_CTR,
+    POLARSSL_CIPHER_AES_256_CTR,
+    POLARSSL_CIPHER_CAMELLIA_128_CBC,
+    POLARSSL_CIPHER_CAMELLIA_192_CBC,
+    POLARSSL_CIPHER_CAMELLIA_256_CBC,
+    POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+    POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+    POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+    POLARSSL_CIPHER_CAMELLIA_128_CTR,
+    POLARSSL_CIPHER_CAMELLIA_192_CTR,
+    POLARSSL_CIPHER_CAMELLIA_256_CTR,
+    POLARSSL_CIPHER_DES_CBC,
+    POLARSSL_CIPHER_DES_EDE_CBC,
+    POLARSSL_CIPHER_DES_EDE3_CBC
+} cipher_type_t;
+
+typedef enum {
+    POLARSSL_MODE_NONE = 0,
+    POLARSSL_MODE_CBC,
+    POLARSSL_MODE_CFB128,
+    POLARSSL_MODE_OFB,
+    POLARSSL_MODE_CTR,
+} cipher_mode_t;
+
+typedef enum {
+    POLARSSL_DECRYPT = 0,
+    POLARSSL_ENCRYPT,
+} operation_t;
+
+enum {
+    /** Undefined key length */
+    POLARSSL_KEY_LENGTH_NONE = 0,
+    /** Key length, in bits, for DES keys */
+    POLARSSL_KEY_LENGTH_DES  = 56,
+    /** Key length, in bits, for DES in two key EDE */
+    POLARSSL_KEY_LENGTH_DES_EDE = 112,
+    /** Key length, in bits, for DES in three-key EDE */
+    POLARSSL_KEY_LENGTH_DES_EDE3 = 168,
+    /** Maximum length of any IV, in bytes */
+    POLARSSL_MAX_IV_LENGTH = 16,
+};
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+typedef struct {
+
+    /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */
+    cipher_id_t cipher;
+
+    /** Encrypt using CBC */
+    int (*cbc_func)( void *ctx, operation_t mode, size_t length, unsigned char *iv,
+            const unsigned char *input, unsigned char *output );
+
+    /** Encrypt using CFB128 */
+    int (*cfb128_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off,
+            unsigned char *iv, const unsigned char *input, unsigned char *output );
+
+    /** Encrypt using CTR */
+    int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter,
+            unsigned char *stream_block, const unsigned char *input, unsigned char *output );
+
+    /** Set key for encryption purposes */
+    int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+
+    /** Set key for decryption purposes */
+    int (*setkey_dec_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)( void );
+
+    /** Free the given context */
+    void (*ctx_free_func)( void *ctx );
+
+} cipher_base_t;
+
+/**
+ * Cipher information. Allows cipher functions to be called in a generic way.
+ */
+typedef struct {
+    /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */
+    cipher_type_t type;
+
+    /** Cipher mode (e.g. POLARSSL_CIPHER_MODE_CBC) */
+    cipher_mode_t mode;
+
+    /** Cipher key length, in bits (default length for variable sized ciphers) */
+    unsigned int key_length;
+
+    /** Name of the cipher */
+    const char * name;
+
+    /** IV size, in bytes */
+    unsigned int iv_size;
+
+    /** block size, in bytes */
+    unsigned int block_size;
+
+    /** Base cipher information and functions */
+    const cipher_base_t *base;
+
+} cipher_info_t;
+
+/**
+ * Generic message digest context.
+ */
+typedef struct {
+    /** Information about the associated cipher */
+    const cipher_info_t *cipher_info;
+
+    /** Key length to use */
+    int key_length;
+
+    /** Operation that the context's key has been initialised for */
+    operation_t operation;
+
+    /** Buffer for data that hasn't been encrypted yet */
+    unsigned char unprocessed_data[POLARSSL_MAX_IV_LENGTH];
+
+    /** Number of bytes that still need processing */
+    size_t unprocessed_len;
+
+    /** Current IV or NONCE_COUNTER for CTR-mode */
+    unsigned char iv[POLARSSL_MAX_IV_LENGTH];
+
+    /** Cipher-specific context */
+    void *cipher_ctx;
+} cipher_context_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Returns the list of ciphers supported by the generic cipher module.
+ *
+ * \return              a statically allocated array of ciphers, the last entry
+ *                      is 0.
+ */
+const int *cipher_list( void );
+
+/**
+ * \brief               Returns the cipher information structure associated
+ *                      with the given cipher name.
+ *
+ * \param cipher_name   Name of the cipher to search for.
+ *
+ * \return              the cipher information structure associated with the
+ *                      given cipher_name, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_string( const char *cipher_name );
+
+/**
+ * \brief               Returns the cipher information structure associated
+ *                      with the given cipher type.
+ *
+ * \param cipher_type   Type of the cipher to search for.
+ *
+ * \return              the cipher information structure associated with the
+ *                      given cipher_type, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type );
+
+/**
+ * \brief               Initialises and fills the cipher context structure with
+ *                      the appropriate values.
+ *
+ * \param ctx           context to initialise. May not be NULL.
+ * \param cipher_info   cipher to use.
+ *
+ * \return              \c 0 on success,
+ *                      \c POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
+ *                      \c POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ *                      cipher-specific context failed.
+ */
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info );
+
+/**
+ * \brief               Free the cipher-specific context of ctx. Freeing ctx
+ *                      itself remains the responsibility of the caller.
+ *
+ * \param ctx           Free the cipher-specific context
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails.
+ */
+int cipher_free_ctx( cipher_context_t *ctx );
+
+/**
+ * \brief               Returns the block size of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              size of the cipher's blocks, or 0 if ctx has not been
+ *                      initialised.
+ */
+static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief               Returns the size of the cipher's IV.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              size of the cipher's IV, or 0 if ctx has not been
+ *                      initialised.
+ */
+static inline int cipher_get_iv_size( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->iv_size;
+}
+
+/**
+ * \brief               Returns the type of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              type of the cipher, or POLARSSL_CIPHER_NONE if ctx has
+ *                      not been initialised.
+ */
+static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return (cipher_type_t)0;
+
+    return ctx->cipher_info->type;
+}
+
+/**
+ * \brief               Returns the name of the given cipher, as a string.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              name of the cipher, or NULL if ctx was not initialised.
+ */
+static inline const char *cipher_get_name( const cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->name;
+}
+
+/**
+ * \brief               Returns the key length of the cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              cipher's key length, in bits, or
+ *                      POLARSSL_KEY_LENGTH_NONE if ctx has not been
+ *                      initialised.
+ */
+static inline int cipher_get_key_size ( const cipher_context_t *ctx )
+{
+    if( NULL == ctx )
+        return POLARSSL_KEY_LENGTH_NONE;
+
+    return ctx->key_length;
+}
+
+/**
+ * \brief               Set the key to use with the given context.
+ *
+ * \param ctx           generic cipher context. May not be NULL. Must have been
+ *                      initialised using cipher_context_from_type or
+ *                      cipher_context_from_string.
+ * \param key           The key to use.
+ * \param key_length    key length to use, in bits.
+ * \param operation     Operation that the key will be used for, either
+ *                      POLARSSL_ENCRYPT or POLARSSL_DECRYPT.
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails or a cipher specific
+ *                      error code.
+ */
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int key_length,
+        const operation_t operation );
+
+/**
+ * \brief               Reset the given context, setting the IV to iv
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use or NONCE_COUNTER in the case of a CTR-mode cipher
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
+ *                      if parameter verification fails.
+ */
+int cipher_reset( cipher_context_t *ctx, const unsigned char *iv );
+
+/**
+ * \brief               Generic cipher update function. Encrypts/decrypts
+ *                      using the given cipher context. Writes as many block
+ *                      size'd blocks of data as possible to output. Any data
+ *                      that cannot be written immediately will either be added
+ *                      to the next block, or flushed when cipher_final is
+ *                      called.
+ *
+ * \param ctx           generic cipher context
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data. Should be able to hold at
+ *                      least ilen + block_size. Cannot be the same buffer as
+ *                      input!
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails,
+ *                      POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ *                      unsupported mode for a cipher or a cipher specific
+ *                      error code.
+ */
+int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
+        unsigned char *output, size_t *olen );
+
+/**
+ * \brief               Generic cipher finalisation function. If data still
+ *                      needs to be flushed from an incomplete block, data
+ *                      contained within it will be padded with the size of
+ *                      the last block, and written to the output buffer.
+ *
+ * \param ctx           Generic message digest context
+ * \param output        buffer to write data to. Needs block_size data available.
+ * \param olen          length of the data written to the output buffer.
+ *
+ * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails,
+ *                      POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ *                      expected a full block but was not provided one,
+ *                      POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting or a cipher specific error code.
+ */
+int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen);
+
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int cipher_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_H */

+ 92 - 0
thirdparty/PolarSSL/include/polarssl/cipher_wrap.h

@@ -0,0 +1,92 @@
+/**
+ * \file cipher_wrap.h
+ * 
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "polarssl/cipher.h"
+
+#ifndef POLARSSL_CIPHER_WRAP_H
+#define POLARSSL_CIPHER_WRAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_AES_C)
+
+extern const cipher_info_t aes_128_cbc_info;
+extern const cipher_info_t aes_192_cbc_info;
+extern const cipher_info_t aes_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+extern const cipher_info_t aes_128_cfb128_info;
+extern const cipher_info_t aes_192_cfb128_info;
+extern const cipher_info_t aes_256_cfb128_info;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+extern const cipher_info_t aes_128_ctr_info;
+extern const cipher_info_t aes_192_ctr_info;
+extern const cipher_info_t aes_256_ctr_info;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif /* defined(POLARSSL_AES_C) */
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+extern const cipher_info_t camellia_128_cbc_info;
+extern const cipher_info_t camellia_192_cbc_info;
+extern const cipher_info_t camellia_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+extern const cipher_info_t camellia_128_cfb128_info;
+extern const cipher_info_t camellia_192_cfb128_info;
+extern const cipher_info_t camellia_256_cfb128_info;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+extern const cipher_info_t camellia_128_ctr_info;
+extern const cipher_info_t camellia_192_ctr_info;
+extern const cipher_info_t camellia_256_ctr_info;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif /* defined(POLARSSL_CAMELLIA_C) */
+
+#if defined(POLARSSL_DES_C)
+
+extern const cipher_info_t des_cbc_info;
+extern const cipher_info_t des_ede_cbc_info;
+extern const cipher_info_t des_ede3_cbc_info;
+
+#endif /* defined(POLARSSL_DES_C) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_CIPHER_WRAP_H */

+ 628 - 0
thirdparty/PolarSSL/include/polarssl/config.h

@@ -0,0 +1,628 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#define free vPortFree
+#define malloc pvPortMalloc
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT8
+ *
+ * The system uses 8-bit wide native integers.
+ *
+ * Uncomment if native integers are 8-bit wide.
+#define POLARSSL_HAVE_INT8
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT16
+ *
+ * The system uses 16-bit wide native integers.
+ *
+ * Uncomment if native integers are 16-bit wide.
+#define POLARSSL_HAVE_INT16
+ */
+
+/**
+ * \def POLARSSL_HAVE_LONGLONG
+ *
+ * The compiler supports the use of long long.
+ *
+ * Uncomment if the compiler supports long long.
+#define POLARSSL_HAVE_LONGLONG
+ */
+
+/**
+ * \def POLARSSL_HAVE_ASM
+ *
+ * The compiler has support for asm()
+ *
+ * Uncomment to enable the use of assembly code.
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/polarssl/bn_mul.h
+ *
+ */
+//#define POLARSSL_HAVE_ASM
+
+/**
+ * \def POLARSSL_HAVE_SSE2
+ *
+ * CPI supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ *
+#define POLARSSL_HAVE_SSE2
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+#define POLARSSL_AES_ROM_TABLES
+ */
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CFB
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define POLARSSL_CIPHER_MODE_CTR
+
+/**
+ * \def POLARSSL_DEBUG_MSG
+ *
+ * Requires: POLARSSL_DEBUG_C
+ *
+ * Enable all SSL/TLS debugging messages.
+ */
+#define POLARSSL_DEBUG_MSG
+
+/**
+ * \def POLARSSL_GENPRIME
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * Enable the RSA prime-number generation code.
+ */
+#define POLARSSL_GENPRIME
+
+/**
+ * \def POLARSSL_FS_IO
+ *
+ * Enable functions that use the filesystem.
+#define POLARSSL_FS_IO
+ */
+
+/**
+ * \def POLARSSL_PKCS1_V21
+ *
+ * Requires: POLARSSL_MD_C, POLARSSL_RSA_C
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define POLARSSL_PKCS1_V21
+
+/**
+ * \def POLARSSL_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+#define POLARSSL_RSA_NO_CRT
+ */
+
+/**
+ * \def POLARSSL_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+#define POLARSSL_SELF_TEST
+ */
+
+/**
+ * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ *
+#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL modules
+ *
+ * This section enables or disables entire modules in PolarSSL
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module:  library/aes.c
+ * Caller:  library/ssl_tls.c
+ *          library/pem.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_AES_128_SHA
+ *      SSL_RSA_AES_256_SHA
+ *      SSL_EDH_RSA_AES_256_SHA
+ */
+#define POLARSSL_AES_C
+
+/**
+ * \def POLARSSL_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module:  library/arc4.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_RC4_128_MD5
+ *      SSL_RSA_RC4_128_SHA
+ */
+#define POLARSSL_ARC4_C
+
+/**
+ * \def POLARSSL_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module:  library/base64.c
+ * Caller:  library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define POLARSSL_BASE64_C
+
+/**
+ * \def POLARSSL_BIGNUM_C
+ *
+ * Enable the multo-precision integer library.
+ *
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/**
+ * \def POLARSSL_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module:  library/camellia.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enabled the following cipher suites:
+ *      SSL_RSA_CAMELLIA_128_SHA
+ *      SSL_RSA_CAMELLIA_256_SHA
+ *      SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_CAMELLIA_C
+
+/**
+ * \def POLARSSL_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define POLARSSL_CERTS_C
+
+/**
+ * \def POLARSSL_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ * Caller:
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define POLARSSL_CIPHER_C
+
+/**
+ * \def POLARSSL_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/**
+ * \def POLARSSL_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module:  library/des.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_DES_168_SHA
+ *      SSL_EDH_RSA_DES_168_SHA
+ */
+#define POLARSSL_DES_C
+
+/**
+ * \def POLARSSL_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle key exchange.
+ *
+ * Module:  library/dhm.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_EDH_RSA_DES_168_SHA
+ *      SSL_EDH_RSA_AES_256_SHA
+ *      SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_DHM_C
+
+/**
+ * \def POLARSSL_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module:  library/error.c
+ * Caller:
+ *
+ * This module enables err_strerror().
+ */
+#define POLARSSL_ERROR_C
+
+/**
+ * \def POLARSSL_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * Requires: POLARSSL_TIMING_C
+ *
+ * This module enables the HAVEGE random number generator.
+#define POLARSSL_HAVEGE_C
+ */
+
+/**
+ * \def POLARSSL_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module:  library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define POLARSSL_MD_C
+
+/**
+ * \def POLARSSL_MD2_C
+ *
+ * Enable the MD2 hash algorithm
+ *
+ * Module:  library/md2.c
+ * Caller:  library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+#define POLARSSL_MD2_C
+ */
+
+/**
+ * \def POLARSSL_MD4_C
+ *
+ * Enable the MD4 hash algorithm
+ *
+ * Module:  library/md4.c
+ * Caller:  library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+#define POLARSSL_MD4_C
+ */
+
+/**
+ * \def POLARSSL_MD5_C
+ *
+ * Enable the MD5 hash algorithm
+ *
+ * Module:  library/md5.c
+ * Caller:  library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ */
+#define POLARSSL_MD5_C
+
+/**
+ * \def POLARSSL_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module:  library/net.c
+ * Caller:
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define POLARSSL_NET_C
+
+/**
+ * \def POLARSSL_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * This modules adds support for the VIA PadLock on x86.
+#define POLARSSL_PADLOCK_C
+ */
+
+/**
+ * \def POLARSSL_PEM_C
+ *
+ * Enable PEM decoding
+ *
+ * Module:  library/pem.c
+ * Caller:  library/x509parse.c
+ *
+ * Requires: POLARSSL_BASE64_C
+ *
+ * This modules adds support for decoding PEM files.
+ */
+#define POLARSSL_PEM_C
+
+/**
+ * \def POLARSSL_PKCS11_C
+ *
+ * Enable support for PKCS#11 smartcard support.
+ *
+ * Module:  library/ssl_srv.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+#define POLARSSL_PKCS11_C
+ */
+
+/**
+ * \def POLARSSL_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module:  library/rsa.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509.c
+ *
+ * Requires: POLARSSL_BIGNUM_C
+ *
+ * This module is required for SSL/TLS and MD5-signed certificates.
+ */
+#define POLARSSL_RSA_C
+
+/**
+ * \def POLARSSL_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module:  library/sha1.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/**
+ * \def POLARSSL_SHA2_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module:  library/sha2.c
+ * Caller:  library/md_wrap.c
+ *          library/x509parse.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ */
+#define POLARSSL_SHA2_C
+
+/**
+ * \def POLARSSL_SHA4_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module:  library/sha4.c
+ * Caller:  library/md_wrap.c
+ *          library/x509parse.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define POLARSSL_SHA4_C
+
+/**
+ * \def POLARSSL_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+#define POLARSSL_SSL_CLI_C
+ */
+
+/*
+ * \def POLARSSL_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define POLARSSL_SSL_SRV_C
+
+/**
+ * \def POLARSSL_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/**
+ * \def POLARSSL_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+#define POLARSSL_TIMING_C
+ */
+
+/**
+ * \def POLARSSL_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module:  library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define POLARSSL_VERSION_C
+
+/**
+ * \def POLARSSL_X509_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module:  library/x509parse.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_PARSE_C
+
+/**
+ * \def POLARSSL_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module:  library/xtea.c
+ * Caller:
+ */
+#define POLARSSL_XTEA_C
+/* \} name */
+
+#endif /* config.h */

+ 91 - 0
thirdparty/PolarSSL/include/polarssl/debug.h

@@ -0,0 +1,91 @@
+/**
+ * \file debug.h
+ *
+ * \brief Debug functions
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef SSL_DEBUG_H
+#define SSL_DEBUG_H
+
+#include "config.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_DEBUG_MSG) && defined(POLARSSL_DEBUG_C)
+
+#define __FILENAME__ (strrchr(__FILE__, 0x5c) +1)
+
+#define SSL_DEBUG_MSG( level, args )                    \
+    debug_print_msg( ssl, level, __FILENAME__, __LINE__, debug_fmt args );
+
+#define SSL_DEBUG_RET( level, text, ret )                \
+    debug_print_ret( ssl, level, __FILENAME__, __LINE__, text, ret );
+
+#define SSL_DEBUG_BUF( level, text, buf, len )           \
+    debug_print_buf( ssl, level, __FILENAME__, __LINE__, text, buf, len );
+
+#define SSL_DEBUG_MPI( level, text, X )                  \
+    debug_print_mpi( ssl, level, __FILENAME__, __LINE__, text, X );
+
+#define SSL_DEBUG_CRT( level, text, crt )                \
+    debug_print_crt( ssl, level, __FILENAME__, __LINE__, text, crt );
+
+#else
+
+#define SSL_DEBUG_MSG( level, args )            do { } while( 0 )
+#define SSL_DEBUG_RET( level, text, ret )       do { } while( 0 )
+#define SSL_DEBUG_BUF( level, text, buf, len )  do { } while( 0 )
+#define SSL_DEBUG_MPI( level, text, X )         do { } while( 0 )
+#define SSL_DEBUG_CRT( level, text, crt )       do { } while( 0 )
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *debug_fmt( const char *format, ... );
+
+void debug_print_msg( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text );
+
+void debug_print_ret( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, int ret );
+
+void debug_print_buf( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text,
+                      unsigned char *buf, size_t len );
+
+void debug_print_mpi( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const mpi *X );
+
+void debug_print_crt( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const x509_cert *crt );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* debug.h */

+ 235 - 0
thirdparty/PolarSSL/include/polarssl/des.h

@@ -0,0 +1,235 @@
+/**
+ * \file des.h
+ *
+ * \brief DES block cipher
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Note: This file has been modified by ST's MCD Application Team, to support 
+   the hardware crypto engine embedded in STM32F417xx */
+
+#ifndef POLARSSL_DES_H
+#define POLARSSL_DES_H
+
+#include <string.h>
+
+#define DES_ENCRYPT     1
+#define DES_DECRYPT     0
+
+#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH              -0x0032  /**< The data input has an invalid length. */
+
+#define DES_KEY_SIZE    8
+
+/**
+ * \brief          DES context structure
+ */
+typedef struct
+{
+    int mode;                   /*!<  encrypt/decrypt   */
+    unsigned long sk[32];       /*!<  DES subkeys       */
+}
+des_context;
+
+/**
+ * \brief          Triple-DES context structure
+ */
+typedef struct
+{
+    int mode;                   /*!<  encrypt/decrypt   */
+    unsigned long sk[96];       /*!<  3DES subkeys      */
+#ifdef USE_STM32F4XX_HW_CRYPTO 
+    unsigned char tdes_enc_key[24]; /* Encryption key */
+    unsigned char tdes_dec_key[24]; /* Decryption key */
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+}
+des3_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Set key parity on the given key to odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ */
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          Check that key parity on the given key is odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ *
+ * \return         0 is parity was ok, 1 if parity was not correct.
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          Check that key is not a weak or semi-weak DES key
+ *
+ * \param key      8-byte secret key
+ *
+ * \resurn         0 if no weak key was found, 1 if a weak key was identified.
+ */
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          DES key schedule (56-bit, encryption)
+ *
+ * \param ctx      DES context to be initialized
+ * \param key      8-byte secret key
+ *
+ * \return         0
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          DES key schedule (56-bit, decryption)
+ *
+ * \param ctx      DES context to be initialized
+ * \param key      8-byte secret key
+ *
+ * \return         0
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          Triple-DES key schedule (112-bit, encryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      16-byte secret key
+ *
+ * \return         0
+ */
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief          Triple-DES key schedule (112-bit, decryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      16-byte secret key
+ *
+ * \return         0
+ */
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief          Triple-DES key schedule (168-bit, encryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      24-byte secret key
+ *
+ * \return         0
+ */
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief          Triple-DES key schedule (168-bit, decryption)
+ *
+ * \param ctx      3DES context to be initialized
+ * \param key      24-byte secret key
+ *
+ * \return         0
+ */
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief          DES-ECB block encryption/decryption
+ *
+ * \param ctx      DES context
+ * \param input    64-bit input block
+ * \param output   64-bit output block
+ *
+ * \return         0 if successful
+ */
+int des_crypt_ecb( des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] );
+
+/**
+ * \brief          DES-CBC buffer encryption/decryption
+ *
+ * \param ctx      DES context
+ * \param mode     DES_ENCRYPT or DES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ */
+int des_crypt_cbc( des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output );
+
+/**
+ * \brief          3DES-ECB block encryption/decryption
+ *
+ * \param ctx      3DES context
+ * \param input    64-bit input block
+ * \param output   64-bit output block
+ *
+ * \return         0 if successful
+ */
+int des3_crypt_ecb( des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] );
+
+/**
+ * \brief          3DES-CBC buffer encryption/decryption
+ *
+ * \param ctx      3DES context
+ * \param mode     DES_ENCRYPT or DES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH
+ */
+int des3_crypt_cbc( des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output );
+
+/*
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int des_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* des.h */

+ 151 - 0
thirdparty/PolarSSL/include/polarssl/dhm.h

@@ -0,0 +1,151 @@
+/**
+ * \file dhm.h
+ *
+ * \brief Diffie-Hellman-Merkle key exchange
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DHM_H
+#define POLARSSL_DHM_H
+
+#include "polarssl/bignum.h"
+
+/*
+ * DHM Error codes
+ */
+#define POLARSSL_ERR_DHM_BAD_INPUT_DATA                    -0x3080  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED                -0x3100  /**< Reading of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED                -0x3180  /**< Making of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED                -0x3200  /**< Reading of the public values failed. */
+#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED                -0x3280  /**< Makeing of the public value failed. */
+#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED                -0x3300  /**< Calculation of the DHM secret failed. */
+
+/**
+ * \brief          DHM context structure
+ */
+typedef struct
+{
+    size_t len; /*!<  size(P) in chars  */
+    mpi P;      /*!<  prime modulus     */
+    mpi G;      /*!<  generator         */
+    mpi X;      /*!<  secret value      */
+    mpi GX;     /*!<  self = G^X mod P  */
+    mpi GY;     /*!<  peer = G^Y mod P  */
+    mpi K;      /*!<  key = GY^X mod P  */
+    mpi RP;     /*!<  cached R^2 mod P  */
+}
+dhm_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Parse the ServerKeyExchange parameters
+ *
+ * \param ctx      DHM context
+ * \param p        &(start of input buffer)
+ * \param end      end of buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_params( dhm_context *ctx,
+                     unsigned char **p,
+                     const unsigned char *end );
+
+/**
+ * \brief          Setup and write the ServerKeyExchange parameters
+ *
+ * \param ctx      DHM context
+ * \param x_size   private value size in bytes
+ * \param output   destination buffer
+ * \param olen     number of chars written
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \note           This function assumes that ctx->P and ctx->G
+ *                 have already been properly set (for example
+ *                 using mpi_read_string or mpi_read_binary).
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief          Import the peer's public value G^Y
+ *
+ * \param ctx      DHM context
+ * \param input    input buffer
+ * \param ilen     size of buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_public( dhm_context *ctx,
+                     const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          Create own private value X and export G^X
+ *
+ * \param ctx      DHM context
+ * \param x_size   private value size in bits
+ * \param output   destination buffer
+ * \param olen     must be equal to ctx->P.len
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t olen,
+                     int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief          Derive and export the shared secret (G^Y)^X mod P
+ *
+ * \param ctx      DHM context
+ * \param output   destination buffer
+ * \param olen     number of chars written
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_calc_secret( dhm_context *ctx,
+                     unsigned char *output, size_t *olen );
+
+/*
+ * \brief          Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int dhm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 93 - 0
thirdparty/PolarSSL/include/polarssl/error.h

@@ -0,0 +1,93 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ERROR_H
+#define POLARSSL_ERROR_H
+
+/**
+ * Error code layout.
+ *
+ * Currently we try to keep all error codes within the negative space of 16
+ * bytes signed integers to support all platforms (-0x0000 - -0x8000). In
+ * addition we'd like to give two layers of information on the error if
+ * possible.
+ *
+ * For that purpose the error codes are segmented in the following manner:
+ *
+ * 16 bit error code bit-segmentation
+ *
+ * 1 bit  - Intentionally not used
+ * 3 bits - High level module ID
+ * 5 bits - Module-dependent error code
+ * 6 bits - Low level module errors
+ * 1 bit  - Intentionally not used
+ *
+ * Low-level module errors (0x007E-0x0002)
+ *
+ * Module   Nr  Codes assigned 
+ * MPI       7  0x0002-0x000E
+ * BASE64    2  0x0010-0x0012
+ * ASN1      5  0x0014-0x001C
+ * AES       2  0x0020-0x0022
+ * CAMELLIA  2  0x0024-0x0026
+ * XTEA      1  0x0028-0x0028
+ * PADLOCK   1  0x0030-0x0030
+ * DES       1  0x0032-0x0032
+ * NET      11  0x0040-0x0054
+ *
+ * High-level module nr (3 bits - 0x1...-0x8...)
+ * Name     ID  Nr of Errors
+ * PEM      1   8
+ * X509     2   20
+ * DHM      3   6
+ * RSA      4   9
+ * MD       5   1
+ * CIPER    6   1
+ * SSL      7   27
+ *
+ * Module dependent error code (5 bits 0x.08.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translate a PolarSSL error code into a string representation,
+ *        Result is truncated if necessary and always includes a terminating
+ *        null byte.
+ *
+ * \param errnum    error code
+ * \param buffer    buffer to place representation in
+ * \param buflen    length of the buffer
+ */
+void error_strerror( int errnum, char *buffer, size_t buflen );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */

+ 67 - 0
thirdparty/PolarSSL/include/polarssl/havege.h

@@ -0,0 +1,67 @@
+/**
+ * \file havege.h
+ *
+ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_HAVEGE_H
+#define POLARSSL_HAVEGE_H
+
+#define COLLECT_SIZE 1024
+
+/**
+ * \brief          HAVEGE state structure
+ */
+typedef struct
+{
+    int PT1, PT2, offset[2];
+    int pool[COLLECT_SIZE];
+    int WALK[8192];
+}
+havege_state;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          HAVEGE initialization
+ *
+ * \param hs       HAVEGE state to be initialized
+ */
+void havege_init( havege_state *hs );
+
+/**
+ * \brief          HAVEGE rand function
+ *
+ * \param p_rng    A HAVEGE state
+ *
+ * \return         A random int
+ */
+int havege_rand( void *p_rng );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* havege.h */

+ 356 - 0
thirdparty/PolarSSL/include/polarssl/md.h

@@ -0,0 +1,356 @@
+/**
+ * \file md.h
+ * 
+ * \brief Generic message digest wrapper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_MD_H
+#define POLARSSL_MD_H
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE                -0x5080  /**< The selected feature is not available. */
+#define POLARSSL_ERR_MD_BAD_INPUT_DATA                     -0x5100  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MD_ALLOC_FAILED                       -0x5180  /**< Failed to allocate memory. */
+#define POLARSSL_ERR_MD_FILE_OPEN_FAILED                   -0x5200  /**< Opening of file failed. */
+#define POLARSSL_ERR_MD_FILE_READ_FAILED                   -0x5280  /**< Failure when reading from file. */
+
+typedef enum {
+    POLARSSL_MD_NONE=0,
+    POLARSSL_MD_MD2,
+    POLARSSL_MD_MD4,
+    POLARSSL_MD_MD5,
+    POLARSSL_MD_SHA1,
+    POLARSSL_MD_SHA224,
+    POLARSSL_MD_SHA256,
+    POLARSSL_MD_SHA384,
+    POLARSSL_MD_SHA512,
+} md_type_t;
+
+#define POLARSSL_MD_MAX_SIZE         64  /* longest known is SHA512 */
+
+/**
+ * Message digest information. Allows message digest functions to be called
+ * in a generic way.
+ */
+typedef struct {
+    /** Digest identifier */
+    md_type_t type;
+
+    /** Name of the message digest */
+    const char * name;
+
+    /** Output length of the digest function */
+    int size;
+
+    /** Digest initialisation function */
+    void (*starts_func)( void *ctx );
+
+    /** Digest update function */
+    void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+    /** Digest finalisation function */
+    void (*finish_func)( void *ctx, unsigned char *output );
+
+    /** Generic digest function */
+    void (*digest_func)( const unsigned char *input, size_t ilen,
+                            unsigned char *output );
+
+    /** Generic file digest function */
+    int (*file_func)( const char *path, unsigned char *output );
+
+    /** HMAC Initialisation function */
+    void (*hmac_starts_func)( void *ctx, const unsigned char *key, size_t keylen );
+
+    /** HMAC update function */
+    void (*hmac_update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+    /** HMAC finalisation function */
+    void (*hmac_finish_func)( void *ctx, unsigned char *output);
+
+    /** HMAC context reset function */
+    void (*hmac_reset_func)( void *ctx );
+
+    /** Generic HMAC function */
+    void (*hmac_func)( const unsigned char *key, size_t keylen,
+                    const unsigned char *input, size_t ilen,
+                    unsigned char *output );
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)( void );
+
+    /** Free the given context */
+    void (*ctx_free_func)( void *ctx );
+
+} md_info_t;
+
+/**
+ * Generic message digest context.
+ */
+typedef struct {
+    /** Information about the associated message digest */
+    const md_info_t *md_info;
+
+    /** Digest-specific context */
+    void *md_ctx;
+} md_context_t;
+
+#define MD_CONTEXT_T_INIT { \
+    NULL, /* md_info */ \
+    NULL, /* md_ctx */ \
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Returns the list of digests supported by the generic digest module.
+ *
+ * \return          a statically allocated array of digests, the last entry
+ *                  is 0.
+ */
+const int *md_list( void );
+
+/**
+ * \brief           Returns the message digest information associated with the
+ *                  given digest name.
+ *
+ * \param md_name   Name of the digest to search for.
+ *
+ * \return          The message digest information associated with md_name or
+ *                  NULL if not found.
+ */
+const md_info_t *md_info_from_string( const char *md_name );
+
+/**
+ * \brief           Returns the message digest information associated with the
+ *                  given digest type.
+ *
+ * \param md_type   type of digest to search for.
+ *
+ * \return          The message digest information associated with md_type or
+ *                  NULL if not found.
+ */
+const md_info_t *md_info_from_type( md_type_t md_type );
+
+/**
+ * \brief          Initialises and fills the message digest context structure with
+ *                 the appropriate values.
+ *
+ * \param ctx      context to initialise. May not be NULL. The
+ *                 digest-specific context (ctx->md_ctx) must be NULL. It will
+ *                 be allocated, and must be freed using md_free_ctx() later.
+ * \param md_info  message digest to use.
+ *
+ * \returns        \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on
+ *                 parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if
+ *                 allocation of the cipher-specific context failed.
+ */
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
+
+/**
+ * \brief          Free the message-specific context of ctx. Freeing ctx itself
+ *                 remains the responsibility of the caller.
+ *
+ * \param ctx      Free the message-specific context
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_free_ctx( md_context_t *ctx );
+
+/**
+ * \brief           Returns the size of the message digest output.
+ *
+ * \param md_info   message digest info
+ *
+ * \return          size of the message digest output.
+ */
+static inline unsigned char md_get_size( const md_info_t *md_info )
+{
+    return md_info->size;
+}
+
+/**
+ * \brief           Returns the type of the message digest output.
+ *
+ * \param md_info   message digest info
+ *
+ * \return          type of the message digest output.
+ */
+static inline md_type_t md_get_type( const md_info_t *md_info )
+{
+    return md_info->type;
+}
+
+/**
+ * \brief           Returns the name of the message digest output.
+ *
+ * \param md_info   message digest info
+ *
+ * \return          name of the message digest output.
+ */
+static inline const char *md_get_name( const md_info_t *md_info )
+{
+    return md_info->name;
+}
+
+/**
+ * \brief          Set-up the given context for a new message digest
+ *
+ * \param ctx      generic message digest context.
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_starts( md_context_t *ctx );
+
+/**
+ * \brief          Generic message digest process buffer
+ *
+ * \param ctx      Generic message digest context
+ * \param input    buffer holding the  datal
+ * \param ilen     length of the input data
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          Generic message digest final digest
+ *
+ * \param ctx      Generic message digest context
+ * \param output   Generic message digest checksum result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_finish( md_context_t *ctx, unsigned char *output );
+
+/**
+ * \brief          Output = message_digest( input buffer )
+ *
+ * \param md_info  message digest info
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   Generic message digest checksum result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+        unsigned char *output );
+
+/**
+ * \brief          Output = message_digest( file contents )
+ *
+ * \param md_info  message digest info
+ * \param path     input file name
+ * \param output   generic message digest checksum result
+ *
+ * \return         0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen
+ *                 failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed,
+ *                 POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL.
+ */
+int md_file( const md_info_t *md_info, const char *path, unsigned char *output );
+
+/**
+ * \brief          Generic HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          Generic HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          Generic HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   Generic HMAC checksum result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_finish( md_context_t *ctx, unsigned char *output);
+
+/**
+ * \brief          Generic HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac_reset( md_context_t *ctx );
+
+/**
+ * \brief          Output = Generic_HMAC( hmac key, input buffer )
+ *
+ * \param md_info  message digest info
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   Generic HMAC-result
+ *
+ * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ *                 verification fails.
+ */
+int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_H */

+ 152 - 0
thirdparty/PolarSSL/include/polarssl/md2.h

@@ -0,0 +1,152 @@
+/**
+ * \file md2.h
+ *
+ * \brief MD2 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD2_H
+#define POLARSSL_MD2_H
+
+#include <string.h>
+
+/**
+ * \brief          MD2 context structure
+ */
+typedef struct
+{
+    unsigned char cksum[16];    /*!< checksum of the data block */
+    unsigned char state[48];    /*!< intermediate digest state  */
+    unsigned char buffer[16];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+    size_t left;                /*!< amount of data in buffer   */
+}
+md2_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MD2 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void md2_starts( md2_context *ctx );
+
+/**
+ * \brief          MD2 process buffer
+ *
+ * \param ctx      MD2 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD2 final digest
+ *
+ * \param ctx      MD2 context
+ * \param output   MD2 checksum result
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD2( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   MD2 checksum result
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD2( file contents )
+ *
+ * \param path     input file name
+ * \param output   MD2 checksum result
+ *
+ * \return         0 if successful, 1 if fopen failed,
+ *                 or 2 if fread failed
+ */
+int md2_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief          MD2 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          MD2 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD2 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   MD2 HMAC checksum result
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          MD2 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void md2_hmac_reset( md2_context *ctx );
+
+/**
+ * \brief          Output = HMAC-MD2( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-MD2 result
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int md2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md2.h */

+ 151 - 0
thirdparty/PolarSSL/include/polarssl/md4.h

@@ -0,0 +1,151 @@
+/**
+ * \file md4.h
+ *
+ * \brief MD4 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD4_H
+#define POLARSSL_MD4_H
+
+#include <string.h>
+
+/**
+ * \brief          MD4 context structure
+ */
+typedef struct
+{
+    unsigned long total[2];     /*!< number of bytes processed  */
+    unsigned long state[4];     /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+md4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MD4 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void md4_starts( md4_context *ctx );
+
+/**
+ * \brief          MD4 process buffer
+ *
+ * \param ctx      MD4 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD4 final digest
+ *
+ * \param ctx      MD4 context
+ * \param output   MD4 checksum result
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD4( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   MD4 checksum result
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD4( file contents )
+ *
+ * \param path     input file name
+ * \param output   MD4 checksum result
+ *
+ * \return         0 if successful, 1 if fopen failed,
+ *                 or 2 if fread failed
+ */
+int md4_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief          MD4 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          MD4 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD4 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   MD4 HMAC checksum result
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          MD4 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void md4_hmac_reset( md4_context *ctx );
+
+/**
+ * \brief          Output = HMAC-MD4( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-MD4 result
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int md4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md4.h */

+ 153 - 0
thirdparty/PolarSSL/include/polarssl/md5.h

@@ -0,0 +1,153 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD5_H
+#define POLARSSL_MD5_H
+
+#include <string.h>
+
+/**
+ * \brief          MD5 context structure
+ */
+typedef struct
+{
+    unsigned long total[2];     /*!< number of bytes processed  */
+    unsigned long state[4];     /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+md5_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          MD5 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void md5_starts( md5_context *ctx );
+
+/**
+ * \brief          MD5 process buffer
+ *
+ * \param ctx      MD5 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD5 final digest
+ *
+ * \param ctx      MD5 context
+ * \param output   MD5 checksum result
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD5( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   MD5 checksum result
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief          Output = MD5( file contents )
+ *
+ * \param path     input file name
+ * \param output   MD5 checksum result
+ *
+ * \return         0 if successful, 1 if fopen failed,
+ *                 or 2 if fread failed
+ */
+int md5_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief          MD5 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void md5_hmac_starts( md5_context *ctx,
+                      const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          MD5 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void md5_hmac_update( md5_context *ctx,
+                      const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          MD5 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   MD5 HMAC checksum result
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief          MD5 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void md5_hmac_reset( md5_context *ctx );
+
+/**
+ * \brief          Output = HMAC-MD5( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-MD5 result
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int md5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md5.h */

+ 65 - 0
thirdparty/PolarSSL/include/polarssl/md_wrap.h

@@ -0,0 +1,65 @@
+/**
+ * \file md_wrap.h
+ * 
+ * \brief Message digest wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "polarssl/md.h"
+
+#ifndef POLARSSL_MD_WRAP_H
+#define POLARSSL_MD_WRAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_MD2_C)
+extern const md_info_t md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+extern const md_info_t md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+extern const md_info_t md5_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+extern const md_info_t sha1_info;
+#endif
+#if defined(POLARSSL_SHA2_C)
+extern const md_info_t sha224_info;
+extern const md_info_t sha256_info;
+#endif
+#if defined(POLARSSL_SHA4_C)
+extern const md_info_t sha384_info;
+extern const md_info_t sha512_info;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_WRAP_H */

+ 159 - 0
thirdparty/PolarSSL/include/polarssl/net.h

@@ -0,0 +1,159 @@
+/**
+ * \file net.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_NET_H
+#define POLARSSL_NET_H
+
+#include <string.h>
+ 
+#define POLARSSL_ERR_NET_UNKNOWN_HOST                      -0x0040  /**< Failed to get an IP address for the given hostname. */
+#define POLARSSL_ERR_NET_SOCKET_FAILED                     -0x0042  /**< Failed to open a socket. */
+#define POLARSSL_ERR_NET_CONNECT_FAILED                    -0x0044  /**< The connection to the given server / port failed. */
+#define POLARSSL_ERR_NET_BIND_FAILED                       -0x0046  /**< Binding of the socket failed. */
+#define POLARSSL_ERR_NET_LISTEN_FAILED                     -0x0048  /**< Could not listen on the socket. */
+#define POLARSSL_ERR_NET_ACCEPT_FAILED                     -0x004A  /**< Could not accept the incoming connection. */
+#define POLARSSL_ERR_NET_RECV_FAILED                       -0x004C  /**< Reading information from the socket failed. */
+#define POLARSSL_ERR_NET_SEND_FAILED                       -0x004E  /**< Sending information through the socket failed. */
+#define POLARSSL_ERR_NET_CONN_RESET                        -0x0050  /**< Connection was reset by peer. */
+#define POLARSSL_ERR_NET_WANT_READ                         -0x0052  /**< Connection requires a read call. */
+#define POLARSSL_ERR_NET_WANT_WRITE                        -0x0054  /**< Connection requires a write call. */
+
+#define POLARSSL_NET_LISTEN_BACKLOG         10 /**< The backlog that listen() should use. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Initiate a TCP connection with host:port
+ *
+ * \param fd       Socket to use
+ * \param host     Host to connect to
+ * \param port     Port to connect to
+ *
+ * \return         0 if successful, or one of:
+ *                      POLARSSL_ERR_NET_SOCKET_FAILED,
+ *                      POLARSSL_ERR_NET_UNKNOWN_HOST,
+ *                      POLARSSL_ERR_NET_CONNECT_FAILED
+ */
+int net_connect( int *fd, const char *host, int port );
+
+/**
+ * \brief          Create a listening socket on bind_ip:port.
+ *                 If bind_ip == NULL, all interfaces are binded.
+ *
+ * \param fd       Socket to use
+ * \param bind_ip  IP to bind to, can be NULL
+ * \param port     Port number to use
+ *
+ * \return         0 if successful, or one of:
+ *                      POLARSSL_ERR_NET_SOCKET_FAILED,
+ *                      POLARSSL_ERR_NET_BIND_FAILED,
+ *                      POLARSSL_ERR_NET_LISTEN_FAILED
+ */
+int net_bind( int *fd, const char *bind_ip, int port );
+
+/**
+ * \brief           Accept a connection from a remote client
+ *
+ * \param bind_fd   Relevant socket
+ * \param client_fd Will contain the connected client socket
+ * \param client_ip Will contain the client IP address
+ *
+ * \return          0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or
+ *                  POLARSSL_ERR_NET_WOULD_BLOCK is bind_fd was set to
+ *                  non-blocking and accept() is blocking.
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip );
+
+/**
+ * \brief          Set the socket blocking
+ *
+ * \param fd       Socket to set
+ *
+ * \return         0 if successful, or a non-zero error code
+ */
+int net_set_block( int fd );
+
+/**
+ * \brief          Set the socket non-blocking
+ *
+ * \param fd       Socket to set
+ *
+ * \return         0 if successful, or a non-zero error code
+ */
+int net_set_nonblock( int fd );
+
+/**
+ * \brief          Portable usleep helper
+ *
+ * \param usec     Amount of microseconds to sleep
+ *
+ * \note           Real amount of time slept will not be less than
+ *                 select()'s timeout granularity (typically, 10ms).
+ */
+void net_usleep( unsigned long usec );
+
+/**
+ * \brief          Read at most 'len' characters. If no error occurs,
+ *                 the actual amount read is returned.
+ *
+ * \param ctx      Socket
+ * \param buf      The buffer to write to
+ * \param len      Maximum length of the buffer
+ *
+ * \return         This function returns the number of bytes received,
+ *                 or a non-zero error code; POLARSSL_ERR_NET_WANT_READ
+ *                 indicates read() is blocking.
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len );
+
+/**
+ * \brief          Write at most 'len' characters. If no error occurs,
+ *                 the actual amount read is returned.
+ *
+ * \param ctx      Socket
+ * \param buf      The buffer to read from
+ * \param len      The length of the buffer
+ *
+ * \return         This function returns the number of bytes sent,
+ *                 or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE
+ *                 indicates write() is blocking.
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len );
+
+/**
+ * \brief          Gracefully shutdown the connection
+ *
+ * \param fd       The socket to close
+ */
+void net_close( int fd );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* net.h */

+ 136 - 0
thirdparty/PolarSSL/include/polarssl/openssl.h

@@ -0,0 +1,136 @@
+/**
+ * \file openssl.h
+ *
+ * \brief OpenSSL wrapper (definitions, inline functions).
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * OpenSSL wrapper contributed by David Barett
+ */
+#ifndef POLARSSL_OPENSSL_H
+#define POLARSSL_OPENSSL_H
+
+#include "polarssl/aes.h"
+#include "polarssl/md5.h"
+#include "polarssl/rsa.h"
+#include "polarssl/sha1.h"
+
+#define AES_SIZE                16
+#define AES_BLOCK_SIZE          16
+#define AES_KEY                 aes_context
+#define MD5_CTX                 md5_context
+#define SHA_CTX                 sha1_context
+
+#define SHA1_Init( CTX ) \
+        sha1_starts( (CTX) )
+#define SHA1_Update(  CTX, BUF, LEN ) \
+        sha1_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define SHA1_Final( OUT, CTX ) \
+        sha1_finish( (CTX), (OUT) )
+
+#define MD5_Init( CTX ) \
+        md5_starts( (CTX) )
+#define MD5_Update( CTX, BUF, LEN ) \
+        md5_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define MD5_Final( OUT, CTX ) \
+        md5_finish( (CTX), (OUT) )
+
+#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \
+        aes_setkey_enc( (CTX), (KEY), (KEYSIZE) )
+#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \
+        aes_setkey_dec( (CTX), (KEY), (KEYSIZE) )
+#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \
+        aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) )
+
+/*
+ * RSA stuff follows. TODO: needs cleanup
+ */
+inline int __RSA_Passthrough( void *output, void *input, int size )
+{
+    memcpy( output, input, size );
+    return size;
+}
+
+inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr,
+                                    int len )
+{
+    unsigned char *buffer = *(unsigned char **) bufptr;
+    rsa_context *rsa;
+    
+    /*
+     * Not a general-purpose parser: only parses public key from *exactly*
+     *   openssl genrsa -out privkey.pem 512 (or 1024)
+     *   openssl rsa -in privkey.pem -out privatekey.der -outform der
+     *   openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout
+     *
+     * TODO: make a general-purpose parse
+     */
+    if( ignore != 0 || ( len != 94 && len != 162 ) )
+        return( 0 );
+
+    rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) );
+    if( rsa == NULL )
+        return( 0 );
+
+    memset( rsa, 0, sizeof( rsa_context ) );
+
+    if( ( len ==  94 && 
+          mpi_read_binary( &rsa->N, &buffer[ 25],  64 ) == 0 &&
+          mpi_read_binary( &rsa->E, &buffer[ 91],   3 ) == 0 ) ||
+        ( len == 162 &&
+          mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) &&
+          mpi_read_binary( &rsa->E, &buffer[159],   3 ) == 0 )
+    {
+        /*
+         * key read successfully
+         */
+        rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3;
+        return( rsa );
+    }
+    else
+    {
+        memset( rsa, 0, sizeof( rsa_context ) );
+        free( rsa );
+        return( 0 );
+    }
+}
+
+#define RSA                     rsa_context
+#define RSA_PKCS1_PADDING       1 /* ignored; always encrypt with this */
+#define RSA_size( CTX )         (CTX)->len
+#define RSA_free( CTX )         rsa_free( CTX )
+#define ERR_get_error( )        "ERR_get_error() not supported"
+#define RSA_blinding_off( IGNORE )
+
+#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */
+
+inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC,  &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC,  size, input, output ) ) return RSA_size(key); else return -1; }
+inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* openssl.h */

+ 100 - 0
thirdparty/PolarSSL/include/polarssl/padlock.h

@@ -0,0 +1,100 @@
+/**
+ * \file padlock.h
+ *
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some processors
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PADLOCK_H
+#define POLARSSL_PADLOCK_H
+
+#include "polarssl/aes.h"
+
+#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED               -0x0030  /**< Input data should be aligned. */
+
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
+
+#ifndef POLARSSL_HAVE_X86
+#define POLARSSL_HAVE_X86
+#endif
+
+#define PADLOCK_RNG 0x000C
+#define PADLOCK_ACE 0x00C0
+#define PADLOCK_PHE 0x0C00
+#define PADLOCK_PMM 0x3000
+
+#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          PadLock detection routine
+ *
+ * \param          The feature to detect
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int padlock_supports( int feature );
+
+/**
+ * \brief          PadLock AES-ECB block en(de)cryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 if success, 1 if operation failed
+ */
+int padlock_xcryptecb( aes_context *ctx,
+                       int mode,
+                       const unsigned char input[16],
+                       unsigned char output[16] );
+
+/**
+ * \brief          PadLock AES-CBC buffer en(de)cryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if success, 1 if operation failed
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_X86  */
+
+#endif /* padlock.h */

+ 100 - 0
thirdparty/PolarSSL/include/polarssl/pem.h

@@ -0,0 +1,100 @@
+/**
+ * \file pem.h
+ *
+ * \brief Privacy Enhanced Mail (PEM) decoding
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PEM_H
+#define POLARSSL_PEM_H
+
+#include <string.h>
+
+/**
+ * \name PEM Error codes
+ * These error codes are returned in case of errors reading the
+ * PEM data.
+ * \{
+ */
+#define POLARSSL_ERR_PEM_NO_HEADER_PRESENT                 -0x1080  /**< No PEM header found. */
+#define POLARSSL_ERR_PEM_INVALID_DATA                      -0x1100  /**< PEM string is not as expected. */
+#define POLARSSL_ERR_PEM_MALLOC_FAILED                     -0x1180  /**< Failed to allocate memory. */
+#define POLARSSL_ERR_PEM_INVALID_ENC_IV                    -0x1200  /**< RSA IV is not in hex-format. */
+#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG                   -0x1280  /**< Unsupported key encryption algorithm. */
+#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED                 -0x1300  /**< Private key password can't be empty. */
+#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH                 -0x1380  /**< Given private key password does not allow for correct decryption. */
+#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE               -0x1400  /**< Unavailable feature, e.g. hashing/encryption combination. */
+/* \} name */
+
+/**
+ * \brief       PEM context structure
+ */
+typedef struct
+{
+    unsigned char *buf;     /*!< buffer for decoded data             */
+    size_t buflen;          /*!< length of the buffer                */
+    unsigned char *info;    /*!< buffer for extra header information */
+}
+pem_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief       PEM context setup
+ *
+ * \param ctx   context to be initialized
+ */
+void pem_init( pem_context *ctx );
+
+/**
+ * \brief       Read a buffer for PEM information and store the resulting
+ *              data into the specified context buffers.
+ *
+ * \param ctx       context to use
+ * \param header    header string to seek and expect
+ * \param footer    footer string to seek and expect
+ * \param data      source data to look in
+ * \param pwd       password for decryption (can be NULL)
+ * \param pwdlen    length of password
+ * \param use_len   destination for total length used
+ *
+ * \return          0 on success, ior a specific PEM error code
+ */
+int pem_read_buffer( pem_context *ctx, char *header, char *footer,
+                     const unsigned char *data,
+                     const unsigned char *pwd,
+                     size_t pwdlen, size_t *use_len );
+
+/**
+ * \brief       PEM context memory freeing
+ *
+ * \param ctx   context to be freed
+ */
+void pem_free( pem_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pem.h */

+ 127 - 0
thirdparty/PolarSSL/include/polarssl/pkcs11.h

@@ -0,0 +1,127 @@
+/**
+ * \file pkcs11.h
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef PKCS11_H_
+#define PKCS11_H_
+
+#include "config.h"
+
+#if defined(POLARSSL_PKCS11_C)
+
+#include "polarssl/x509.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
+
+/**
+ * Context for PKCS #11 private keys.
+ */
+typedef struct {
+        pkcs11h_certificate_t pkcs11h_cert;
+        int len;
+} pkcs11_context;
+
+/**
+ * Fill in a PolarSSL certificate, based on the given PKCS11 helper certificate.
+ *
+ * \param cert          X.509 certificate to fill
+ * \param pkcs11h_cert  PKCS #11 helper certificate
+ *
+ * \return              0 on success.
+ */
+int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11h_cert );
+
+/**
+ * Initialise a pkcs11_context, storing the given certificate. Note that the
+ * pkcs11_context will take over control of the certificate, freeing it when
+ * done.
+ *
+ * \param priv_key      Private key structure to fill.
+ * \param pkcs11_cert   PKCS #11 helper certificate
+ *
+ * \return              0 on success
+ */
+int pkcs11_priv_key_init( pkcs11_context *priv_key,
+        pkcs11h_certificate_t pkcs11_cert );
+
+/**
+ * Free the contents of the given private key context. Note that the structure
+ * itself is not freed.
+ *
+ * \param priv_key      Private key structure to cleanup
+ */
+void pkcs11_priv_key_free( pkcs11_context *priv_key );
+
+/**
+ * \brief          Do an RSA private key decrypt, then remove the message padding
+ *
+ * \param ctx      PKCS #11 context
+ * \param mode     must be RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param input    buffer holding the encrypted data
+ * \param output   buffer that will hold the plaintext
+ * \param olen     will contain the plaintext length
+ * \param output_max_len    maximum length of the output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The output buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ *                 an error is thrown.
+ */
+int pkcs11_decrypt( pkcs11_context *ctx,
+                       int mode, size_t *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       unsigned int output_max_len );
+
+/**
+ * \brief          Do a private RSA to sign a message digest
+ *
+ * \param ctx      PKCS #11 context
+ * \param mode     must be RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen  message digest length (for SIG_RSA_RAW only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer that will hold the ciphertext
+ *
+ * \return         0 if the signing operation was successful,
+ *                 or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The "sig" buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int pkcs11_sign( pkcs11_context *ctx,
+                    int mode,
+                    int hash_id,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig );
+
+#endif /* POLARSSL_PKCS11_C */
+
+#endif /* PKCS11_H_ */

+ 372 - 0
thirdparty/PolarSSL/include/polarssl/rsa.h

@@ -0,0 +1,372 @@
+/**
+ * \file rsa.h
+ *
+ * \brief The RSA public-key cryptosystem
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_RSA_H
+#define POLARSSL_RSA_H
+
+#include "polarssl/bignum.h"
+
+/*
+ * RSA Error codes
+ */
+#define POLARSSL_ERR_RSA_BAD_INPUT_DATA                    -0x4080  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_RSA_INVALID_PADDING                   -0x4100  /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_RSA_KEY_GEN_FAILED                    -0x4180  /**< Something failed during generation of a key. */
+#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED                  -0x4200  /**< Key failed to pass the libraries validity check. */
+#define POLARSSL_ERR_RSA_PUBLIC_FAILED                     -0x4280  /**< The public key operation failed. */
+#define POLARSSL_ERR_RSA_PRIVATE_FAILED                    -0x4300  /**< The private key operation failed. */
+#define POLARSSL_ERR_RSA_VERIFY_FAILED                     -0x4380  /**< The PKCS#1 verification failed. */
+#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE                  -0x4400  /**< The output buffer for decryption is not large enough. */
+#define POLARSSL_ERR_RSA_RNG_FAILED                        -0x4480  /**< The random generator failed to generate non-zeros. */
+
+/*
+ * PKCS#1 constants
+ */
+#define SIG_RSA_RAW     0
+#define SIG_RSA_MD2     2
+#define SIG_RSA_MD4     3
+#define SIG_RSA_MD5     4
+#define SIG_RSA_SHA1    5
+#define SIG_RSA_SHA224 14
+#define SIG_RSA_SHA256 11
+#define SIG_RSA_SHA384 12
+#define SIG_RSA_SHA512 13
+
+#define RSA_PUBLIC      0
+#define RSA_PRIVATE     1
+
+#define RSA_PKCS_V15    0
+#define RSA_PKCS_V21    1
+
+#define RSA_SIGN        1
+#define RSA_CRYPT       2
+
+#define ASN1_STR_CONSTRUCTED_SEQUENCE   "\x30"
+#define ASN1_STR_NULL                   "\x05"
+#define ASN1_STR_OID                    "\x06"
+#define ASN1_STR_OCTET_STRING           "\x04"
+
+#define OID_DIGEST_ALG_MDX              "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
+#define OID_HASH_ALG_SHA1               "\x2b\x0e\x03\x02\x1a"
+#define OID_HASH_ALG_SHA2X              "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
+
+#define OID_ISO_MEMBER_BODIES           "\x2a"
+#define OID_ISO_IDENTIFIED_ORG          "\x2b"
+
+/*
+ * ISO Member bodies OID parts
+ */
+#define OID_COUNTRY_US                  "\x86\x48"
+#define OID_RSA_DATA_SECURITY           "\x86\xf7\x0d"
+
+/*
+ * ISO Identified organization OID parts
+ */
+#define OID_OIW_SECSIG_SHA1             "\x0e\x03\x02\x1a"
+
+/*
+ * DigestInfo ::= SEQUENCE {
+ *   digestAlgorithm DigestAlgorithmIdentifier,
+ *   digest Digest }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * Digest ::= OCTET STRING
+ */
+#define ASN1_HASH_MDX                           \
+(                                               \
+    ASN1_STR_CONSTRUCTED_SEQUENCE "\x20"        \
+      ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C"      \
+        ASN1_STR_OID "\x08"                     \
+      OID_DIGEST_ALG_MDX                        \
+    ASN1_STR_NULL "\x00"                        \
+      ASN1_STR_OCTET_STRING "\x10"              \
+)
+
+#define ASN1_HASH_SHA1                          \
+    ASN1_STR_CONSTRUCTED_SEQUENCE "\x21"        \
+      ASN1_STR_CONSTRUCTED_SEQUENCE "\x09"      \
+        ASN1_STR_OID "\x05"                     \
+      OID_HASH_ALG_SHA1                         \
+        ASN1_STR_NULL "\x00"                    \
+      ASN1_STR_OCTET_STRING "\x14"
+
+#define ASN1_HASH_SHA2X                         \
+    ASN1_STR_CONSTRUCTED_SEQUENCE "\x11"        \
+      ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d"      \
+        ASN1_STR_OID "\x09"                     \
+      OID_HASH_ALG_SHA2X                        \
+        ASN1_STR_NULL "\x00"                    \
+      ASN1_STR_OCTET_STRING "\x00"
+
+/**
+ * \brief          RSA context structure
+ */
+typedef struct
+{
+    int ver;                    /*!<  always 0          */
+    size_t len;                 /*!<  size(N) in chars  */
+
+    mpi N;                      /*!<  public modulus    */
+    mpi E;                      /*!<  public exponent   */
+
+    mpi D;                      /*!<  private exponent  */
+    mpi P;                      /*!<  1st prime factor  */
+    mpi Q;                      /*!<  2nd prime factor  */
+    mpi DP;                     /*!<  D % (P - 1)       */
+    mpi DQ;                     /*!<  D % (Q - 1)       */
+    mpi QP;                     /*!<  1 / (Q % P)       */
+
+    mpi RN;                     /*!<  cached R^2 mod N  */
+    mpi RP;                     /*!<  cached R^2 mod P  */
+    mpi RQ;                     /*!<  cached R^2 mod Q  */
+
+    int padding;                /*!<  RSA_PKCS_V15 for 1.5 padding and
+                                      RSA_PKCS_v21 for OAEP/PSS         */
+    int hash_id;                /*!<  Hash identifier of md_type_t as
+                                      specified in the md.h header file
+                                      for the EME-OAEP and EMSA-PSS
+                                      encoding                          */
+}
+rsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Initialize an RSA context
+ *
+ * \param ctx      RSA context to be initialized
+ * \param padding  RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id  RSA_PKCS_V21 hash identifier
+ *
+ * \note           The hash_id parameter is actually ignored
+ *                 when using RSA_PKCS_V15 padding.
+ */
+void rsa_init( rsa_context *ctx,
+               int padding,
+               int hash_id);
+
+/**
+ * \brief          Generate an RSA keypair
+ *
+ * \param ctx      RSA context that will hold the key
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ * \param nbits    size of the public key in bits
+ * \param exponent public exponent (e.g., 65537)
+ *
+ * \note           rsa_init() must be called beforehand to setup
+ *                 the RSA context.
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_gen_key( rsa_context *ctx,
+                 int (*f_rng)(void *),
+                 void *p_rng,
+                 unsigned int nbits, int exponent );
+
+/**
+ * \brief          Check a public RSA key
+ *
+ * \param ctx      RSA context to be checked
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_pubkey( const rsa_context *ctx );
+
+/**
+ * \brief          Check a private RSA key
+ *
+ * \param ctx      RSA context to be checked
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_privkey( const rsa_context *ctx );
+
+/**
+ * \brief          Do an RSA public key operation
+ *
+ * \param ctx      RSA context
+ * \param input    input buffer
+ * \param output   output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           This function does NOT take care of message
+ *                 padding. Also, be sure to set input[0] = 0 or assure that
+ *                 input is smaller than N.
+ *
+ * \note           The input and output buffers must be large
+ *                 enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_public( rsa_context *ctx,
+                const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief          Do an RSA private key operation
+ *
+ * \param ctx      RSA context
+ * \param input    input buffer
+ * \param output   output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The input and output buffers must be large
+ *                 enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_private( rsa_context *ctx,
+                 const unsigned char *input,
+                 unsigned char *output );
+
+/**
+ * \brief          Add the message padding, then do an RSA operation
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for padding and PKCS#1 v2.1 encoding)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen     contains the plaintext length
+ * \param input    buffer holding the data to be encrypted
+ * \param output   buffer that will hold the ciphertext
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The output buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+                       int (*f_rng)(void *),
+                       void *p_rng,
+                       int mode, size_t ilen,
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/**
+ * \brief          Do an RSA operation, then remove the message padding
+ *
+ * \param ctx      RSA context
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param olen     will contain the plaintext length
+ * \param input    buffer holding the encrypted data
+ * \param output   buffer that will hold the plaintext
+ * \param output_max_len    maximum length of the output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The output buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ *                 an error is thrown.
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+                       int mode, size_t *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       size_t output_max_len );
+
+/**
+ * \brief          Do a private RSA to sign a message digest
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function (Needed for PKCS#1 v2.1 encoding)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen  message digest length (for SIG_RSA_RAW only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer that will hold the ciphertext
+ *
+ * \return         0 if the signing operation was successful,
+ *                 or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The "sig" buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note           In case of PKCS#1 v2.1 encoding keep in mind that
+ *                 the hash_id in the RSA context is the one used for the
+ *                 encoding. hash_id in the function call is the type of hash
+ *                 that is encoded. According to RFC 3447 it is advised to
+ *                 keep both hashes the same.
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+                    int (*f_rng)(void *),
+                    void *p_rng,
+                    int mode,
+                    int hash_id,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig );
+
+/**
+ * \brief          Do a public RSA and check the message digest
+ *
+ * \param ctx      points to an RSA public key
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen  message digest length (for SIG_RSA_RAW only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer holding the ciphertext
+ *
+ * \return         0 if the verify operation was successful,
+ *                 or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The "sig" buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note           In case of PKCS#1 v2.1 encoding keep in mind that
+ *                 the hash_id in the RSA context is the one used for the
+ *                 verification. hash_id in the function call is the type of hash
+ *                 that is verified. According to RFC 3447 it is advised to
+ *                 keep both hashes the same.
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+                      int mode,
+                      int hash_id,
+                      unsigned int hashlen,
+                      const unsigned char *hash,
+                      unsigned char *sig );
+
+/**
+ * \brief          Free the components of an RSA key
+ *
+ * \param ctx      RSA Context to free
+ */
+void rsa_free( rsa_context *ctx );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int rsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa.h */

+ 151 - 0
thirdparty/PolarSSL/include/polarssl/sha1.h

@@ -0,0 +1,151 @@
+/**
+ * \file sha1.h
+ *
+ * \brief SHA-1 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA1_H
+#define POLARSSL_SHA1_H
+
+#include <string.h>
+
+/**
+ * \brief          SHA-1 context structure
+ */
+typedef struct
+{
+    unsigned long total[2];     /*!< number of bytes processed  */
+    unsigned long state[5];     /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+sha1_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SHA-1 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void sha1_starts( sha1_context *ctx );
+
+/**
+ * \brief          SHA-1 process buffer
+ *
+ * \param ctx      SHA-1 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-1 final digest
+ *
+ * \param ctx      SHA-1 context
+ * \param output   SHA-1 checksum result
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief          Output = SHA-1( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SHA-1 checksum result
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
+
+/**
+ * \brief          Output = SHA-1( file contents )
+ *
+ * \param path     input file name
+ * \param output   SHA-1 checksum result
+ *
+ * \return         0 if successful, 1 if fopen failed,
+ *                 or 2 if fread failed
+ */
+int sha1_file( const char *path, unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          SHA-1 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-1 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SHA-1 HMAC checksum result
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief          SHA-1 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void sha1_hmac_reset( sha1_context *ctx );
+
+/**
+ * \brief          Output = HMAC-SHA-1( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SHA-1 result
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[20] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha1.h */

+ 159 - 0
thirdparty/PolarSSL/include/polarssl/sha2.h

@@ -0,0 +1,159 @@
+/**
+ * \file sha2.h
+ *
+ * \brief SHA-224 and SHA-256 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA2_H
+#define POLARSSL_SHA2_H
+
+#include <string.h>
+
+/**
+ * \brief          SHA-256 context structure
+ */
+typedef struct
+{
+    unsigned long total[2];     /*!< number of bytes processed  */
+    unsigned long state[8];     /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+    int is224;                  /*!< 0 => SHA-256, else SHA-224 */
+}
+sha2_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SHA-256 context setup
+ *
+ * \param ctx      context to be initialized
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha2_starts( sha2_context *ctx, int is224 );
+
+/**
+ * \brief          SHA-256 process buffer
+ *
+ * \param ctx      SHA-256 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-256 final digest
+ *
+ * \param ctx      SHA-256 context
+ * \param output   SHA-224/256 checksum result
+ */
+void sha2_finish( sha2_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief          Output = SHA-256( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SHA-224/256 checksum result
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha2( const unsigned char *input, size_t ilen,
+           unsigned char output[32], int is224 );
+
+/**
+ * \brief          Output = SHA-256( file contents )
+ *
+ * \param path     input file name
+ * \param output   SHA-224/256 checksum result
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ *
+ * \return         0 if successful, 1 if fopen failed,
+ *                 or 2 if fread failed
+ */
+int sha2_file( const char *path, unsigned char output[32], int is224 );
+
+/**
+ * \brief          SHA-256 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
+                       int is224 );
+
+/**
+ * \brief          SHA-256 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-256 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SHA-224/256 HMAC checksum result
+ */
+void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief          SHA-256 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void sha2_hmac_reset( sha2_context *ctx );
+
+/**
+ * \brief          Output = HMAC-SHA-256( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SHA-224/256 result
+ * \param is224    0 = use SHA256, 1 = use SHA224
+ */
+void sha2_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[32], int is224 );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int sha2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha2.h */

+ 167 - 0
thirdparty/PolarSSL/include/polarssl/sha4.h

@@ -0,0 +1,167 @@
+/**
+ * \file sha4.h
+ *
+ * \brief SHA-384 and SHA-512 cryptographic hash function
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA4_H
+#define POLARSSL_SHA4_H
+
+#include <string.h>
+
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+  #define UL64(x) x##ui64
+  #define int64 __int64
+#else
+  #define UL64(x) x##ULL
+  #define int64 long long
+#endif
+
+/**
+ * \brief          SHA-512 context structure
+ */
+typedef struct
+{
+    unsigned int64 total[2];    /*!< number of bytes processed  */
+    unsigned int64 state[8];    /*!< intermediate digest state  */
+    unsigned char buffer[128];  /*!< data block being processed */
+
+    unsigned char ipad[128];    /*!< HMAC: inner padding        */
+    unsigned char opad[128];    /*!< HMAC: outer padding        */
+    int is384;                  /*!< 0 => SHA-512, else SHA-384 */
+}
+sha4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SHA-512 context setup
+ *
+ * \param ctx      context to be initialized
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ */
+void sha4_starts( sha4_context *ctx, int is384 );
+
+/**
+ * \brief          SHA-512 process buffer
+ *
+ * \param ctx      SHA-512 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-512 final digest
+ *
+ * \param ctx      SHA-512 context
+ * \param output   SHA-384/512 checksum result
+ */
+void sha4_finish( sha4_context *ctx, unsigned char output[64] );
+
+/**
+ * \brief          Output = SHA-512( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SHA-384/512 checksum result
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ */
+void sha4( const unsigned char *input, size_t ilen,
+           unsigned char output[64], int is384 );
+
+/**
+ * \brief          Output = SHA-512( file contents )
+ *
+ * \param path     input file name
+ * \param output   SHA-384/512 checksum result
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ *
+ * \return         0 if successful, 1 if fopen failed,
+ *                 or 2 if fread failed
+ */
+int sha4_file( const char *path, unsigned char output[64], int is384 );
+
+/**
+ * \brief          SHA-512 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
+                       int is384 );
+
+/**
+ * \brief          SHA-512 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sha4_hmac_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          SHA-512 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SHA-384/512 HMAC checksum result
+ */
+void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] );
+
+/**
+ * \brief          SHA-512 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void sha4_hmac_reset( sha4_context *ctx );
+
+/**
+ * \brief          Output = HMAC-SHA-512( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SHA-384/512 result
+ * \param is384    0 = use SHA512, 1 = use SHA384
+ */
+void sha4_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[64], int is384 );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int sha4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha4.h */

+ 683 - 0
thirdparty/PolarSSL/include/polarssl/ssl.h

@@ -0,0 +1,683 @@
+/**
+ * \file ssl.h
+ *
+ * \brief SSL/TLS functions.
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_H
+#define POLARSSL_SSL_H
+
+#include <time.h>
+
+#include "polarssl/net.h"
+#include "polarssl/dhm.h"
+#include "polarssl/rsa.h"
+#include "polarssl/md5.h"
+#include "polarssl/sha1.h"
+#include "polarssl/x509.h"
+#include "config.h"
+
+#if defined(POLARSSL_PKCS11_C)
+#include "polarssl/pkcs11.h"
+#endif
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+/*
+ * SSL Error codes
+ */
+#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE               -0x7080  /**< The requested feature is not available. */
+#define POLARSSL_ERR_SSL_BAD_INPUT_DATA                    -0x7100  /**< Bad input parameters to function. */
+#define POLARSSL_ERR_SSL_INVALID_MAC                       -0x7180  /**< Verification of the message MAC failed. */
+#define POLARSSL_ERR_SSL_INVALID_RECORD                    -0x7200  /**< An invalid SSL record was received. */
+#define POLARSSL_ERR_SSL_CONN_EOF                          -0x7280  /**< The connection indicated an EOF. */
+#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER                    -0x7300  /**< An unknown cipher was received. */
+#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN                  -0x7380  /**< The server has no ciphersuites in common with the client. */
+#define POLARSSL_ERR_SSL_NO_SESSION_FOUND                  -0x7400  /**< No session to recover was found. */
+#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE             -0x7480  /**< No client certification received from the client, but required by the authentication mode. */
+#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE             -0x7500  /**< Our own certificate(s) is/are too large to send in an SSL message.*/
+#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED              -0x7580  /**< The own certificate is not set, but needed by the server. */
+#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED              -0x7600  /**< The own private key is not set, but needed. */
+#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED                 -0x7680  /**< No CA Chain is set, but required to operate. */
+#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE                -0x7700  /**< An unexpected message was received from our peer. */
+#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE               -0x7780  /**< A fatal alert message was received from our peer. */
+#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED                -0x7800  /**< Verification of our peer failed. */
+#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY                 -0x7880  /**< The peer notified us that the connection is going to be closed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO               -0x7900  /**< Processing of the ClientHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO               -0x7980  /**< Processing of the ServerHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE                -0x7A00  /**< Processing of the Certificate handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST        -0x7A80  /**< Processing of the CertificateRequest handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE        -0x7B00  /**< Processing of the ServerKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE          -0x7B80  /**< Processing of the ServerHelloDone handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE        -0x7C00  /**< Processing of the ClientKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP -0x7C80  /**< Processing of the ClientKeyExchange handshake message failed in DHM Read Public. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS -0x7D00  /**< Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY         -0x7D80  /**< Processing of the CertificateVerify handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC         -0x7E00  /**< Processing of the ChangeCipherSpec handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_FINISHED                   -0x7E80  /**< Processing of the Finished handshake message failed. */
+
+/*
+ * Various constants
+ */
+#define SSL_MAJOR_VERSION_3             3
+#define SSL_MINOR_VERSION_0             0   /*!< SSL v3.0 */
+#define SSL_MINOR_VERSION_1             1   /*!< TLS v1.0 */
+#define SSL_MINOR_VERSION_2             2   /*!< TLS v1.1 */
+
+#define SSL_IS_CLIENT                   0
+#define SSL_IS_SERVER                   1
+#define SSL_COMPRESS_NULL               0
+
+#define SSL_VERIFY_NONE                 0
+#define SSL_VERIFY_OPTIONAL             1
+#define SSL_VERIFY_REQUIRED             2
+
+//#define SSL_MAX_CONTENT_LEN         16384
+#define SSL_MAX_CONTENT_LEN         2024
+
+/*
+ * Allow an extra 512 bytes for the record header
+ * and encryption overhead (counter + MAC + padding).
+ */
+#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + 512)
+
+/*
+ * Supported ciphersuites
+ */
+#define SSL_RSA_RC4_128_MD5          0x04
+#define SSL_RSA_RC4_128_SHA          0x05
+#define SSL_RSA_DES_168_SHA          0x0A
+#define SSL_EDH_RSA_DES_168_SHA      0x16
+#define SSL_RSA_AES_128_SHA          0x2F
+#define SSL_EDH_RSA_AES_128_SHA      0x33
+#define SSL_RSA_AES_256_SHA          0x35
+#define SSL_EDH_RSA_AES_256_SHA      0x39
+
+#define SSL_RSA_CAMELLIA_128_SHA     0x41
+#define SSL_EDH_RSA_CAMELLIA_128_SHA 0x45
+#define SSL_RSA_CAMELLIA_256_SHA     0x84
+#define SSL_EDH_RSA_CAMELLIA_256_SHA 0x88
+
+/*
+ * Message, alert and handshake types
+ */
+#define SSL_MSG_CHANGE_CIPHER_SPEC     20
+#define SSL_MSG_ALERT                  21
+#define SSL_MSG_HANDSHAKE              22
+#define SSL_MSG_APPLICATION_DATA       23
+
+#define SSL_ALERT_LEVEL_WARNING         1
+#define SSL_ALERT_LEVEL_FATAL           2
+
+#define SSL_ALERT_MSG_CLOSE_NOTIFY           0
+#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE    10
+#define SSL_ALERT_MSG_BAD_RECORD_MAC        20
+#define SSL_ALERT_MSG_DECRYPTION_FAILED     21
+#define SSL_ALERT_MSG_RECORD_OVERFLOW       22
+#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30
+#define SSL_ALERT_MSG_HANDSHAKE_FAILURE     40
+#define SSL_ALERT_MSG_NO_CERT               41
+#define SSL_ALERT_MSG_BAD_CERT              42
+#define SSL_ALERT_MSG_UNSUPPORTED_CERT      43
+#define SSL_ALERT_MSG_CERT_REVOKED          44
+#define SSL_ALERT_MSG_CERT_EXPIRED          45
+#define SSL_ALERT_MSG_CERT_UNKNOWN          46
+#define SSL_ALERT_MSG_ILLEGAL_PARAMETER     47
+#define SSL_ALERT_MSG_UNKNOWN_CA            48
+#define SSL_ALERT_MSG_ACCESS_DENIED         49
+#define SSL_ALERT_MSG_DECODE_ERROR          50
+#define SSL_ALERT_MSG_DECRYPT_ERROR         51
+#define SSL_ALERT_MSG_EXPORT_RESTRICTION    60
+#define SSL_ALERT_MSG_PROTOCOL_VERSION      70
+#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71
+#define SSL_ALERT_MSG_INTERNAL_ERROR        80
+#define SSL_ALERT_MSG_USER_CANCELED         90
+#define SSL_ALERT_MSG_NO_RENEGOTIATION     100
+
+#define SSL_HS_HELLO_REQUEST            0
+#define SSL_HS_CLIENT_HELLO             1
+#define SSL_HS_SERVER_HELLO             2
+#define SSL_HS_CERTIFICATE             11
+#define SSL_HS_SERVER_KEY_EXCHANGE     12
+#define SSL_HS_CERTIFICATE_REQUEST     13
+#define SSL_HS_SERVER_HELLO_DONE       14
+#define SSL_HS_CERTIFICATE_VERIFY      15
+#define SSL_HS_CLIENT_KEY_EXCHANGE     16
+#define SSL_HS_FINISHED                20
+
+/*
+ * TLS extensions
+ */
+#define TLS_EXT_SERVERNAME              0
+#define TLS_EXT_SERVERNAME_HOSTNAME     0
+
+/*
+ * SSL state machine
+ */
+typedef enum
+{
+    SSL_HELLO_REQUEST,
+    SSL_CLIENT_HELLO,
+    SSL_SERVER_HELLO,
+    SSL_SERVER_CERTIFICATE,
+    SSL_SERVER_KEY_EXCHANGE,
+    SSL_CERTIFICATE_REQUEST,
+    SSL_SERVER_HELLO_DONE,
+    SSL_CLIENT_CERTIFICATE,
+    SSL_CLIENT_KEY_EXCHANGE,
+    SSL_CERTIFICATE_VERIFY,
+    SSL_CLIENT_CHANGE_CIPHER_SPEC,
+    SSL_CLIENT_FINISHED,
+    SSL_SERVER_CHANGE_CIPHER_SPEC,
+    SSL_SERVER_FINISHED,
+    SSL_FLUSH_BUFFERS,
+    SSL_HANDSHAKE_OVER
+}
+ssl_states;
+
+typedef struct _ssl_session ssl_session;
+typedef struct _ssl_context ssl_context;
+
+/*
+ * This structure is used for session resuming.
+ */
+struct _ssl_session
+{
+    time_t start;               /*!< starting time      */
+    int ciphersuite;            /*!< chosen ciphersuite */
+    size_t length;              /*!< session id length  */
+    unsigned char id[32];       /*!< session identifier */
+    unsigned char master[48];   /*!< the master secret  */
+    ssl_session *next;          /*!< next session entry */
+};
+
+struct _ssl_context
+{
+    /*
+     * Miscellaneous
+     */
+    int state;                  /*!< SSL handshake: current state     */
+
+    int major_ver;              /*!< equal to  SSL_MAJOR_VERSION_3    */
+    int minor_ver;              /*!< either 0 (SSL3) or 1 (TLS1.0)    */
+
+    int max_major_ver;          /*!< max. major version from client   */
+    int max_minor_ver;          /*!< max. minor version from client   */
+
+    /*
+     * Callbacks (RNG, debug, I/O, verification)
+     */
+    int  (*f_rng)(void *);
+    void (*f_dbg)(void *, int, const char *);
+    int (*f_recv)(void *, unsigned char *, size_t);
+    int (*f_send)(void *, const unsigned char *, size_t);
+    int (*f_vrfy)(void *, x509_cert *, int, int);
+
+    void *p_rng;                /*!< context for the RNG function     */
+    void *p_dbg;                /*!< context for the debug function   */
+    void *p_recv;               /*!< context for reading operations   */
+    void *p_send;               /*!< context for writing operations   */
+    void *p_vrfy;               /*!< context for verification */
+
+    /*
+     * Session layer
+     */
+    int resume;                         /*!<  session resuming flag   */
+    int timeout;                        /*!<  sess. expiration time   */
+    ssl_session *session;               /*!<  current session data    */
+    int (*s_get)(ssl_context *);        /*!<  (server) get callback   */
+    int (*s_set)(ssl_context *);        /*!<  (server) set callback   */
+
+    /*
+     * Record layer (incoming data)
+     */
+    unsigned char *in_ctr;      /*!< 64-bit incoming message counter  */
+    unsigned char *in_hdr;      /*!< 5-byte record header (in_ctr+8)  */
+    unsigned char *in_msg;      /*!< the message contents (in_hdr+5)  */
+    unsigned char *in_offt;     /*!< read offset in application data  */
+
+    int in_msgtype;             /*!< record header: message type      */
+    size_t in_msglen;           /*!< record header: message length    */
+    size_t in_left;             /*!< amount of data read so far       */
+
+    size_t in_hslen;            /*!< current handshake message length */
+    int nb_zero;                /*!< # of 0-length encrypted messages */
+
+    /*
+     * Record layer (outgoing data)
+     */
+    unsigned char *out_ctr;     /*!< 64-bit outgoing message counter  */
+    unsigned char *out_hdr;     /*!< 5-byte record header (out_ctr+8) */
+    unsigned char *out_msg;     /*!< the message contents (out_hdr+5) */
+
+    int out_msgtype;            /*!< record header: message type      */
+    size_t out_msglen;          /*!< record header: message length    */
+    size_t out_left;            /*!< amount of data not yet written   */
+
+    /*
+     * PKI layer
+     */
+    rsa_context *rsa_key;               /*!<  own RSA private key     */
+#if defined(POLARSSL_PKCS11_C)
+    pkcs11_context *pkcs11_key;         /*!<  own PKCS#11 RSA private key */
+#endif
+    x509_cert *own_cert;                /*!<  own X.509 certificate   */
+    x509_cert *ca_chain;                /*!<  own trusted CA chain    */
+    x509_crl *ca_crl;                   /*!<  trusted CA CRLs         */
+    x509_cert *peer_cert;               /*!<  peer X.509 cert chain   */
+    const char *peer_cn;                /*!<  expected peer CN        */
+
+    int endpoint;                       /*!<  0: client, 1: server    */
+    int authmode;                       /*!<  verification mode       */
+    int client_auth;                    /*!<  flag for client auth.   */
+    int verify_result;                  /*!<  verification result     */
+
+    /*
+     * Crypto layer
+     */
+    dhm_context dhm_ctx;                /*!<  DHM key exchange        */
+    md5_context fin_md5;                /*!<  Finished MD5 checksum   */
+    sha1_context fin_sha1;              /*!<  Finished SHA-1 checksum */
+
+    int do_crypt;                       /*!<  en(de)cryption flag     */
+    int *ciphersuites;                  /*!<  allowed ciphersuites    */
+    size_t pmslen;                      /*!<  premaster length        */
+    unsigned int keylen;                /*!<  symmetric key length    */
+    size_t minlen;                      /*!<  min. ciphertext length  */
+    size_t ivlen;                       /*!<  IV length               */
+    size_t maclen;                      /*!<  MAC length              */
+
+    unsigned char randbytes[64];        /*!<  random bytes            */
+    unsigned char premaster[256];       /*!<  premaster secret        */
+
+    unsigned char iv_enc[16];           /*!<  IV (encryption)         */
+    unsigned char iv_dec[16];           /*!<  IV (decryption)         */
+
+    unsigned char mac_enc[32];          /*!<  MAC (encryption)        */
+    unsigned char mac_dec[32];          /*!<  MAC (decryption)        */
+
+    unsigned long ctx_enc[128];         /*!<  encryption context      */
+    unsigned long ctx_dec[128];         /*!<  decryption context      */
+
+    /*
+     * TLS extensions
+     */
+    unsigned char *hostname;
+    size_t         hostname_len;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ssl_default_ciphersuites[];
+
+/**
+ * \brief Returns the list of ciphersuites supported by the SSL/TLS module.
+ *
+ * \return              a statically allocated array of ciphersuites, the last
+ *                      entry is 0.
+ */
+static inline const int *ssl_list_ciphersuites( void )
+{
+    return ssl_default_ciphersuites;
+}
+
+/**
+ * \brief               Return the name of the ciphersuite associated with the given
+ *                      ID
+ *
+ * \param ciphersuite_id SSL ciphersuite ID
+ *
+ * \return              a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id );
+
+/**
+ * \brief               Return the ID of the ciphersuite associated with the given
+ *                      name
+ *
+ * \param ciphersuite_name SSL ciphersuite name
+ *
+ * \return              the ID with the ciphersuite or 0 if not found
+ */
+int ssl_get_ciphersuite_id( const char *ciphersuite_name );
+
+/**
+ * \brief          Initialize an SSL context
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, or 1 if memory allocation failed
+ */
+int ssl_init( ssl_context *ssl );
+
+/**
+ * \brief          Set the current endpoint type
+ *
+ * \param ssl      SSL context
+ * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint );
+
+/**
+ * \brief          Set the certificate verification mode
+ *
+ * \param ssl      SSL context
+ * \param authmode can be:
+ *
+ *  SSL_VERIFY_NONE:      peer certificate is not checked (default),
+ *                        this is insecure and SHOULD be avoided.
+ *
+ *  SSL_VERIFY_OPTIONAL:  peer certificate is checked, however the
+ *                        handshake continues even if verification failed;
+ *                        ssl_get_verify_result() can be called after the
+ *                        handshake is complete.
+ *
+ *  SSL_VERIFY_REQUIRED:  peer *must* present a valid certificate,
+ *                        handshake is aborted if verification failed.
+ */
+void ssl_set_authmode( ssl_context *ssl, int authmode );
+
+/**
+ * \brief          Set the verification callback (Optional).
+ *
+ *                 If set, the verification callback is called once for every
+ *                 certificate in the chain. The verification function has the
+ *                 following parameter: (void *parameter, x509_cert certificate,
+ *                 int certifcate_depth, int preverify_ok). It should
+ *                 return 0 on SUCCESS.
+ *
+ * \param ssl      SSL context
+ * \param f_vrfy   verification function
+ * \param p_vrfy   verification parameter
+ */
+void ssl_set_verify( ssl_context *ssl,
+                     int (*f_vrfy)(void *, x509_cert *, int, int),
+                     void *p_vrfy );
+
+/**
+ * \brief          Set the random number generator callback
+ *
+ * \param ssl      SSL context
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ */
+void ssl_set_rng( ssl_context *ssl,
+                  int (*f_rng)(void *),
+                  void *p_rng );
+
+/**
+ * \brief          Set the debug callback
+ *
+ * \param ssl      SSL context
+ * \param f_dbg    debug function
+ * \param p_dbg    debug parameter
+ */
+void ssl_set_dbg( ssl_context *ssl,
+                  void (*f_dbg)(void *, int, const char *),
+                  void  *p_dbg );
+
+/**
+ * \brief          Set the underlying BIO read and write callbacks
+ *
+ * \param ssl      SSL context
+ * \param f_recv   read callback
+ * \param p_recv   read parameter
+ * \param f_send   write callback
+ * \param p_send   write parameter
+ */
+void ssl_set_bio( ssl_context *ssl,
+        int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+        int (*f_send)(void *, const unsigned char *, size_t), void *p_send );
+
+/**
+ * \brief          Set the session callbacks (server-side only)
+ *
+ * \param ssl      SSL context
+ * \param s_get    session get callback
+ * \param s_set    session set callback
+ */
+void ssl_set_scb( ssl_context *ssl,
+                  int (*s_get)(ssl_context *),
+                  int (*s_set)(ssl_context *) );
+
+/**
+ * \brief          Set the session resuming flag, timeout and data
+ *
+ * \param ssl      SSL context
+ * \param resume   if 0 (default), the session will not be resumed
+ * \param timeout  session timeout in seconds, or 0 (no timeout)
+ * \param session  session context
+ */
+void ssl_set_session( ssl_context *ssl, int resume, int timeout,
+                      ssl_session *session );
+
+/**
+ * \brief               Set the list of allowed ciphersuites
+ *
+ * \param ssl           SSL context
+ * \param ciphersuites  0-terminated list of allowed ciphersuites
+ */
+void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites );
+
+/**
+ * \brief          Set the data required to verify peer certificate
+ *
+ * \param ssl      SSL context
+ * \param ca_chain trusted CA chain
+ * \param ca_crl   trusted CA CRLs
+ * \param peer_cn  expected peer CommonName (or NULL)
+ *
+ * \note           TODO: add two more parameters: depth and crl
+ */
+void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+                       x509_crl *ca_crl, const char *peer_cn );
+
+/**
+ * \brief          Set own certificate and private key
+ *
+ * \param ssl      SSL context
+ * \param own_cert own public certificate
+ * \param rsa_key  own private RSA key
+ */
+void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+                       rsa_context *rsa_key );
+
+#if defined(POLARSSL_PKCS11_C)
+/**
+ * \brief          Set own certificate and PKCS#11 private key
+ *
+ * \param ssl      SSL context
+ * \param own_cert own public certificate
+ * \param pkcs11_key    own PKCS#11 RSA key
+ */
+void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert,
+                       pkcs11_context *pkcs11_key );
+#endif
+
+/**
+ * \brief          Set the Diffie-Hellman public P and G values,
+ *                 read as hexadecimal strings (server-side only)
+ *
+ * \param ssl      SSL context
+ * \param dhm_P    Diffie-Hellman-Merkle modulus
+ * \param dhm_G    Diffie-Hellman-Merkle generator
+ *
+ * \return         0 if successful
+ */
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G );
+
+/**
+ * \brief          Set the Diffie-Hellman public P and G values,
+ *                 read from existing context (server-side only)
+ *
+ * \param ssl      SSL context
+ * \param dhm_ctx  Diffie-Hellman-Merkle context
+ *
+ * \return         0 if successful
+ */
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
+
+/**
+ * \brief          Set hostname for ServerName TLS Extension
+ *                 
+ *
+ * \param ssl      SSL context
+ * \param hostname the server hostname
+ *
+ * \return         0 if successful
+ */
+int ssl_set_hostname( ssl_context *ssl, const char *hostname );
+
+/**
+ * \brief          Return the number of data bytes available to read
+ *
+ * \param ssl      SSL context
+ *
+ * \return         how many bytes are available in the read buffer
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl );
+
+/**
+ * \brief          Return the result of the certificate verification
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, or a combination of:
+ *                      BADCERT_EXPIRED
+ *                      BADCERT_REVOKED
+ *                      BADCERT_CN_MISMATCH
+ *                      BADCERT_NOT_TRUSTED
+ */
+int ssl_get_verify_result( const ssl_context *ssl );
+
+/**
+ * \brief          Return the name of the current ciphersuite
+ *
+ * \param ssl      SSL context
+ *
+ * \return         a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite( const ssl_context *ssl );
+
+/**
+ * \brief          Return the current SSL version (SSLv3/TLSv1/etc)
+ *
+ * \param ssl      SSL context
+ *
+ * \return         a string containing the SSL version
+ */
+const char *ssl_get_version( const ssl_context *ssl );
+
+/**
+ * \brief          Perform the SSL handshake
+ *
+ * \param ssl      SSL context
+ *
+ * \return         0 if successful, POLARSSL_ERR_NET_WANT_READ,
+ *                 POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
+ */
+int ssl_handshake( ssl_context *ssl );
+
+/**
+ * \brief          Read at most 'len' application data bytes
+ *
+ * \param ssl      SSL context
+ * \param buf      buffer that will hold the data
+ * \param len      how many bytes must be read
+ *
+ * \return         This function returns the number of bytes read, 0 for EOF,
+ *                 or a negative error code.
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len );
+
+/**
+ * \brief          Write exactly 'len' application data bytes
+ *
+ * \param ssl      SSL context
+ * \param buf      buffer holding the data
+ * \param len      how many bytes must be written
+ *
+ * \return         This function returns the number of bytes written,
+ *                 or a negative error code.
+ *
+ * \note           When this function returns POLARSSL_ERR_NET_WANT_WRITE,
+ *                 it must be called later with the *same* arguments,
+ *                 until it returns a positive value.
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len );
+
+/**
+ * \brief          Notify the peer that the connection is being closed
+ *
+ * \param ssl      SSL context
+ */
+int ssl_close_notify( ssl_context *ssl );
+
+/**
+ * \brief          Free an SSL context
+ *
+ * \param ssl      SSL context
+ */
+void ssl_free( ssl_context *ssl );
+
+/*
+ * Internal functions (do not call directly)
+ */
+int ssl_handshake_client( ssl_context *ssl );
+int ssl_handshake_server( ssl_context *ssl );
+
+int ssl_derive_keys( ssl_context *ssl );
+void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] );
+
+int ssl_read_record( ssl_context *ssl );
+/**
+ * \return         0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or
+ *                 another negative error code.
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want );
+
+int ssl_write_record( ssl_context *ssl );
+int ssl_flush_output( ssl_context *ssl );
+
+int ssl_parse_certificate( ssl_context *ssl );
+int ssl_write_certificate( ssl_context *ssl );
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl );
+int ssl_write_change_cipher_spec( ssl_context *ssl );
+
+int ssl_parse_finished( ssl_context *ssl );
+int ssl_write_finished( ssl_context *ssl );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl.h */

+ 75 - 0
thirdparty/PolarSSL/include/polarssl/timing.h

@@ -0,0 +1,75 @@
+/**
+ * \file timing.h
+ *
+ * \brief Portable interface to the CPU cycle counter
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_TIMING_H
+#define POLARSSL_TIMING_H
+
+/**
+ * \brief          timer structure
+ */
+struct hr_time
+{
+    unsigned char opaque[32];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern volatile int alarmed;
+
+/**
+ * \brief          Return the CPU cycle counter value
+ */
+unsigned long hardclock( void );
+
+/**
+ * \brief          Return the elapsed time in milliseconds
+ *
+ * \param val      points to a timer structure
+ * \param reset    if set to 1, the timer is restarted
+ */
+unsigned long get_timer( struct hr_time *val, int reset );
+
+/**
+ * \brief          Setup an alarm clock
+ *
+ * \param seconds  delay before the "alarmed" flag is set
+ */
+void set_alarm( int seconds );
+
+/**
+ * \brief          Sleep for a certain amount of time
+ *
+ * \param milliseconds  delay in milliseconds
+ */
+void m_sleep( int milliseconds );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* timing.h */

+ 81 - 0
thirdparty/PolarSSL/include/polarssl/version.h

@@ -0,0 +1,81 @@
+/**
+ * \file version.h
+ *
+ * \brief Run-time version information
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This set of compile-time defines and run-time variables can be used to
+ * determine the version number of the PolarSSL library used.
+ */
+#ifndef POLARSSL_VERSION_H
+#define POLARSSL_VERSION_H
+
+#include "config.h"
+
+/**
+ * The version number x.y.z is split into three parts.
+ * Major, Minor, Patchlevel
+ */
+#define POLARSSL_VERSION_MAJOR  1
+#define POLARSSL_VERSION_MINOR  0
+#define POLARSSL_VERSION_PATCH  0
+
+/**
+ * The single version number has the following structure:
+ *    MMNNPP00
+ *    Major version | Minor version | Patch version
+ */
+#define POLARSSL_VERSION_NUMBER         0x01000000
+#define POLARSSL_VERSION_STRING         "1.0.0"
+#define POLARSSL_VERSION_STRING_FULL    "PolarSSL 1.0.0"
+
+#if defined(POLARSSL_VERSION_C)
+
+/**
+ * Get the version number.
+ *
+ * \return          The constructed version number in the format
+ *                  MMNNPP00 (Major, Minor, Patch).
+ */
+unsigned int version_get_number( void );
+
+/**
+ * Get the version string ("x.y.z").
+ *
+ * \param string    The string that will receive the value.
+ *                  (Should be at least 9 bytes in size)
+ */
+void version_get_string( char *string );
+
+/**
+ * Get the full version string ("PolarSSL x.y.z").
+ *
+ * \param string    The string that will receive the value.
+ *                  (Should be at least 18 bytes in size)
+ */
+void version_get_string_full( char *string );
+
+#endif /* POLARSSL_VERSION_C */
+
+#endif /* version.h */

+ 777 - 0
thirdparty/PolarSSL/include/polarssl/x509.h

@@ -0,0 +1,777 @@
+/**
+ * \file x509.h
+ *
+ * \brief X.509 certificate and private key decoding
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_X509_H
+#define POLARSSL_X509_H
+
+#include "polarssl/rsa.h"
+#include "polarssl/dhm.h"
+
+/** 
+ * \addtogroup x509_module
+ * \{ 
+ */
+ 
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity. 
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define POLARSSL_ERR_ASN1_OUT_OF_DATA                      -0x0014  /**< Out of data when parsing an ASN1 data structure. */
+#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG                   -0x0016  /**< ASN1 tag was of an unexpected value. */
+#define POLARSSL_ERR_ASN1_INVALID_LENGTH                   -0x0018  /**< Error when trying to determine the length or invalid length. */
+#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH                  -0x001A  /**< Actual length differs from expected length. */
+#define POLARSSL_ERR_ASN1_INVALID_DATA                     -0x001C  /**< Data is invalid. (not used) */
+/* \} name */
+
+/** 
+ * \name X509 Error codes
+ * \{
+ */
+#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE              -0x2080  /**< Unavailable feature, e.g. RSA hashing/encryption combination. */
+#define POLARSSL_ERR_X509_CERT_INVALID_PEM                 -0x2100  /**< The PEM-encoded certificate contains invalid elements, e.g. invalid character. */ 
+#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT              -0x2180  /**< The certificate format is invalid, e.g. different type expected. */
+#define POLARSSL_ERR_X509_CERT_INVALID_VERSION             -0x2200  /**< The certificate version element is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL              -0x2280  /**< The serial tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_ALG                 -0x2300  /**< The algorithm tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_NAME                -0x2380  /**< The name tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_DATE                -0x2400  /**< The date tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY              -0x2480  /**< The pubkey tag or value is invalid (only RSA is supported). */
+#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE           -0x2500  /**< The signature tag or value invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS          -0x2580  /**< The extension tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION             -0x2600  /**< Certificate or CRL has an unsupported version number. */
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG             -0x2680  /**< Signature algorithm (oid) is unsupported. */
+#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG                   -0x2700  /**< Key algorithm is unsupported (only RSA is supported). */
+#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH                -0x2780  /**< Certificate signature algorithms do not match. (see \c ::x509_cert sig_oid) */
+#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED               -0x2800  /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */
+#define POLARSSL_ERR_X509_KEY_INVALID_VERSION              -0x2880  /**< Unsupported RSA key version */
+#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT               -0x2900  /**< Invalid RSA key tag or value. */
+#define POLARSSL_ERR_X509_POINT_ERROR                      -0x2980  /**< Not used. */
+#define POLARSSL_ERR_X509_VALUE_TO_LENGTH                  -0x2A00  /**< Not used. */
+/* \} name */
+
+
+/**
+ * \name X509 Verify codes
+ * \{
+ */
+#define BADCERT_EXPIRED             0x01  /**< The certificate validity has expired. */
+#define BADCERT_REVOKED             0x02  /**< The certificate has been revoked (is on a CRL). */
+#define BADCERT_CN_MISMATCH         0x04  /**< The certificate Common Name (CN) does not match with the expected CN. */
+#define BADCERT_NOT_TRUSTED         0x08  /**< The certificate is not correctly signed by the trusted CA. */
+#define BADCRL_NOT_TRUSTED          0x10  /**< CRL is not correctly signed by the trusted CA. */
+#define BADCRL_EXPIRED              0x20  /**< CRL is expired. */
+#define BADCERT_MISSING             0x40  /**< Certificate was missing. */
+#define BADCERT_SKIP_VERIFY         0x80  /**< Certificate verification was skipped. */
+/* \} name */
+
+
+/**
+ * \name DER constants
+ * These constants comply with DER encoded the ANS1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::x509_buf.
+ * \{
+ */
+#define ASN1_BOOLEAN                 0x01
+#define ASN1_INTEGER                 0x02
+#define ASN1_BIT_STRING              0x03
+#define ASN1_OCTET_STRING            0x04
+#define ASN1_NULL                    0x05
+#define ASN1_OID                     0x06
+#define ASN1_UTF8_STRING             0x0C
+#define ASN1_SEQUENCE                0x10
+#define ASN1_SET                     0x11
+#define ASN1_PRINTABLE_STRING        0x13
+#define ASN1_T61_STRING              0x14
+#define ASN1_IA5_STRING              0x16
+#define ASN1_UTC_TIME                0x17
+#define ASN1_GENERALIZED_TIME        0x18
+#define ASN1_UNIVERSAL_STRING        0x1C
+#define ASN1_BMP_STRING              0x1E
+#define ASN1_PRIMITIVE               0x00
+#define ASN1_CONSTRUCTED             0x20
+#define ASN1_CONTEXT_SPECIFIC        0x80
+/* \} name */
+/* \} addtogroup x509_module */
+
+/*
+ * various object identifiers
+ */
+#define X520_COMMON_NAME                3
+#define X520_COUNTRY                    6
+#define X520_LOCALITY                   7
+#define X520_STATE                      8
+#define X520_ORGANIZATION              10
+#define X520_ORG_UNIT                  11
+#define PKCS9_EMAIL                     1
+
+#define X509_OUTPUT_DER              0x01
+#define X509_OUTPUT_PEM              0x02
+#define PEM_LINE_LENGTH                72
+#define X509_ISSUER                  0x01
+#define X509_SUBJECT                 0x02
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define OID_SIZE(x) (sizeof(x) - 1)
+
+#define OID_X520                "\x55\x04"
+#define OID_CN                  OID_X520 "\x03"
+
+#define OID_PKCS1               "\x2A\x86\x48\x86\xF7\x0D\x01\x01"
+#define OID_PKCS1_RSA           OID_PKCS1 "\x01"
+
+#define OID_RSA_SHA_OBS         "\x2B\x0E\x03\x02\x1D"
+
+#define OID_PKCS9               "\x2A\x86\x48\x86\xF7\x0D\x01\x09"
+#define OID_PKCS9_EMAIL         OID_PKCS9 "\x01"
+
+/** ISO arc for standard certificate and CRL extensions */
+#define OID_ID_CE               "\x55\x1D" /**< id-ce OBJECT IDENTIFIER  ::=  {joint-iso-ccitt(2) ds(5) 29} */
+
+/**
+ * Private Internet Extensions
+ * { iso(1) identified-organization(3) dod(6) internet(1)
+ *                      security(5) mechanisms(5) pkix(7) }
+ */
+#define OID_PKIX                "\x2B\x06\x01\x05\x05\x07"
+
+/*
+ * OIDs for standard certificate extensions
+ */
+#define OID_AUTHORITY_KEY_IDENTIFIER    OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 } */
+#define OID_SUBJECT_KEY_IDENTIFIER      OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 } */
+#define OID_KEY_USAGE                   OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 } */
+#define OID_CERTIFICATE_POLICIES        OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 } */
+#define OID_POLICY_MAPPINGS             OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::=  { id-ce 33 } */
+#define OID_SUBJECT_ALT_NAME            OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 } */
+#define OID_ISSUER_ALT_NAME             OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::=  { id-ce 18 } */
+#define OID_SUBJECT_DIRECTORY_ATTRS     OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::=  { id-ce 9 } */
+#define OID_BASIC_CONSTRAINTS           OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 } */
+#define OID_NAME_CONSTRAINTS            OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 } */
+#define OID_POLICY_CONSTRAINTS          OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 } */
+#define OID_EXTENDED_KEY_USAGE          OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */
+#define OID_CRL_DISTRIBUTION_POINTS     OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::=  { id-ce 31 } */
+#define OID_INIHIBIT_ANYPOLICY          OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::=  { id-ce 54 } */
+#define OID_FRESHEST_CRL                OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::=  { id-ce 46 } */
+
+/*
+ * X.509 v3 Key Usage Extension flags
+ */
+#define KU_DIGITAL_SIGNATURE            (0x80)  /* bit 0 */
+#define KU_NON_REPUDIATION              (0x40)  /* bit 1 */
+#define KU_KEY_ENCIPHERMENT             (0x20)  /* bit 2 */
+#define KU_DATA_ENCIPHERMENT            (0x10)  /* bit 3 */
+#define KU_KEY_AGREEMENT                (0x08)  /* bit 4 */
+#define KU_KEY_CERT_SIGN                (0x04)  /* bit 5 */
+#define KU_CRL_SIGN                     (0x02)  /* bit 6 */
+
+/*
+ * X.509 v3 Extended key usage OIDs
+ */
+#define OID_ANY_EXTENDED_KEY_USAGE      OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */
+
+#define OID_KP                          OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */
+#define OID_SERVER_AUTH                 OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */
+#define OID_CLIENT_AUTH                 OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */
+#define OID_CODE_SIGNING                OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */
+#define OID_EMAIL_PROTECTION            OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */
+#define OID_TIME_STAMPING               OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
+#define OID_OCSP_SIGNING                OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
+
+#define STRING_SERVER_AUTH              "TLS Web Server Authentication"
+#define STRING_CLIENT_AUTH              "TLS Web Client Authentication"
+#define STRING_CODE_SIGNING             "Code Signing"
+#define STRING_EMAIL_PROTECTION         "E-mail Protection"
+#define STRING_TIME_STAMPING            "Time Stamping"
+#define STRING_OCSP_SIGNING             "OCSP Signing"
+
+/*
+ * OIDs for CRL extensions
+ */
+#define OID_PRIVATE_KEY_USAGE_PERIOD    OID_ID_CE "\x10"
+#define OID_CRL_NUMBER                  OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */
+
+/*
+ * Netscape certificate extensions
+ */
+#define OID_NETSCAPE                "\x60\x86\x48\x01\x86\xF8\x42" /**< Netscape OID */
+#define OID_NS_CERT                 OID_NETSCAPE "\x01"
+#define OID_NS_CERT_TYPE            OID_NS_CERT  "\x01"
+#define OID_NS_BASE_URL             OID_NS_CERT  "\x02"
+#define OID_NS_REVOCATION_URL       OID_NS_CERT  "\x03"
+#define OID_NS_CA_REVOCATION_URL    OID_NS_CERT  "\x04"
+#define OID_NS_RENEWAL_URL          OID_NS_CERT  "\x07"
+#define OID_NS_CA_POLICY_URL        OID_NS_CERT  "\x08"
+#define OID_NS_SSL_SERVER_NAME      OID_NS_CERT  "\x0C"
+#define OID_NS_COMMENT              OID_NS_CERT  "\x0D"
+#define OID_NS_DATA_TYPE            OID_NETSCAPE "\x02"
+#define OID_NS_CERT_SEQUENCE        OID_NS_DATA_TYPE "\x05"
+
+/*
+ * Netscape certificate types
+ * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html)
+ */
+
+#define NS_CERT_TYPE_SSL_CLIENT         (0x80)  /* bit 0 */
+#define NS_CERT_TYPE_SSL_SERVER         (0x40)  /* bit 1 */
+#define NS_CERT_TYPE_EMAIL              (0x20)  /* bit 2 */
+#define NS_CERT_TYPE_OBJECT_SIGNING     (0x10)  /* bit 3 */
+#define NS_CERT_TYPE_RESERVED           (0x08)  /* bit 4 */
+#define NS_CERT_TYPE_SSL_CA             (0x04)  /* bit 5 */
+#define NS_CERT_TYPE_EMAIL_CA           (0x02)  /* bit 6 */
+#define NS_CERT_TYPE_OBJECT_SIGNING_CA  (0x01)  /* bit 7 */
+
+#define EXT_AUTHORITY_KEY_IDENTIFIER    (1 << 0)
+#define EXT_SUBJECT_KEY_IDENTIFIER      (1 << 1)
+#define EXT_KEY_USAGE                   (1 << 2)
+#define EXT_CERTIFICATE_POLICIES        (1 << 3)
+#define EXT_POLICY_MAPPINGS             (1 << 4)
+#define EXT_SUBJECT_ALT_NAME            (1 << 5)
+#define EXT_ISSUER_ALT_NAME             (1 << 6)
+#define EXT_SUBJECT_DIRECTORY_ATTRS     (1 << 7)
+#define EXT_BASIC_CONSTRAINTS           (1 << 8)
+#define EXT_NAME_CONSTRAINTS            (1 << 9)
+#define EXT_POLICY_CONSTRAINTS          (1 << 10)
+#define EXT_EXTENDED_KEY_USAGE          (1 << 11)
+#define EXT_CRL_DISTRIBUTION_POINTS     (1 << 12)
+#define EXT_INIHIBIT_ANYPOLICY          (1 << 13)
+#define EXT_FRESHEST_CRL                (1 << 14)
+
+#define EXT_NS_CERT_TYPE                (1 << 16)
+
+/** 
+ * \addtogroup x509_module
+ * \{ */
+
+/**
+ * \name Structures for parsing X.509 certificates and CRLs
+ * \{
+ */
+ 
+/** 
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef struct _x509_buf
+{
+    int tag;                /**< ASN1 type, e.g. ASN1_UTF8_STRING. */
+    size_t len;             /**< ASN1 length, e.g. in octets. */
+    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */
+}
+x509_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct _x509_bitstring
+{
+    size_t len;                 /**< ASN1 length, e.g. in octets. */
+    unsigned char unused_bits;  /**< Number of unused bits at the end of the string */
+    unsigned char *p;           /**< Raw ASN1 data for the bit string */
+}
+x509_bitstring;
+
+/**
+ * Container for ASN1 named information objects. 
+ * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.).
+ */
+typedef struct _x509_name
+{
+    x509_buf oid;               /**< The object identifier. */
+    x509_buf val;               /**< The named value. */
+    struct _x509_name *next;    /**< The next named information object. */
+}
+x509_name;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct _x509_sequence
+{
+    x509_buf buf;                   /**< Buffer containing the given ASN.1 item. */
+    struct _x509_sequence *next;    /**< The next entry in the sequence. */
+}
+x509_sequence;
+
+/** Container for date and time (precision in seconds). */
+typedef struct _x509_time
+{
+    int year, mon, day;         /**< Date. */
+    int hour, min, sec;         /**< Time. */
+}
+x509_time;
+
+/** 
+ * Container for an X.509 certificate. The certificate may be chained.
+ */
+typedef struct _x509_cert
+{
+    x509_buf raw;               /**< The raw certificate data (DER). */
+    x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+    int version;                /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
+    x509_buf serial;            /**< Unique id for certificate issued by a specific CA. */
+    x509_buf sig_oid1;          /**< Signature algorithm, e.g. sha1RSA */
+
+    x509_buf issuer_raw;        /**< The raw issuer data (DER). Used for quick comparison. */
+    x509_buf subject_raw;       /**< The raw subject data (DER). Used for quick comparison. */
+
+    x509_name issuer;           /**< The parsed issuer data (named information object). */
+    x509_name subject;          /**< The parsed subject data (named information object). */
+
+    x509_time valid_from;       /**< Start time of certificate validity. */
+    x509_time valid_to;         /**< End time of certificate validity. */
+
+    x509_buf pk_oid;            /**< Subject public key info. Includes the public key algorithm and the key itself. */
+    rsa_context rsa;            /**< Container for the RSA context. Only RSA is supported for public keys at this time. */
+
+    x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
+    x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
+    x509_buf v3_ext;            /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */
+
+    int ext_types;              /**< Bit string containing detected and parsed extensions */
+    int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
+    int max_pathlen;            /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. */
+
+    unsigned char key_usage;    /**< Optional key usage extension value: See the values below */
+
+    x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
+
+    unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values below */
+
+    x509_buf sig_oid2;          /**< Signature algorithm. Must match sig_oid1. */
+    x509_buf sig;               /**< Signature: hash of the tbs part signed with the private key. */
+    int sig_alg;                /**< Internal representation of the signature algorithm, e.g. SIG_RSA_MD2 */
+
+    struct _x509_cert *next;    /**< Next certificate in the CA-chain. */ 
+}
+x509_cert;
+
+/** 
+ * Certificate revocation list entry. 
+ * Contains the CA-specific serial numbers and revocation dates.
+ */
+typedef struct _x509_crl_entry
+{
+    x509_buf raw;
+
+    x509_buf serial;
+
+    x509_time revocation_date;
+
+    x509_buf entry_ext;
+
+    struct _x509_crl_entry *next;
+}
+x509_crl_entry;
+
+/** 
+ * Certificate revocation list structure. 
+ * Every CRL may have multiple entries.
+ */
+typedef struct _x509_crl
+{
+    x509_buf raw;           /**< The raw certificate data (DER). */
+    x509_buf tbs;           /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+    int version;
+    x509_buf sig_oid1;
+
+    x509_buf issuer_raw;    /**< The raw issuer data (DER). */
+
+    x509_name issuer;       /**< The parsed issuer data (named information object). */
+
+    x509_time this_update;  
+    x509_time next_update;
+
+    x509_crl_entry entry;   /**< The CRL entries containing the certificate revocation times for this CA. */
+
+    x509_buf crl_ext;
+
+    x509_buf sig_oid2;
+    x509_buf sig;
+    int sig_alg;
+
+    struct _x509_crl *next; 
+}
+x509_crl;
+/** \} name Structures for parsing X.509 certificates and CRLs */
+/** \} addtogroup x509_module */
+
+/**
+ * \name Structures for writing X.509 certificates.
+ * XvP: commented out as they are not used.
+ * - <tt>typedef struct _x509_node x509_node;</tt>
+ * - <tt>typedef struct _x509_raw x509_raw;</tt>
+ */
+/*
+typedef struct _x509_node
+{
+    unsigned char *data;
+    unsigned char *p;
+    unsigned char *end;
+
+    size_t len;
+}
+x509_node;
+
+typedef struct _x509_raw
+{
+    x509_node raw;
+    x509_node tbs;
+
+    x509_node version;
+    x509_node serial;
+    x509_node tbs_signalg;
+    x509_node issuer;
+    x509_node validity;
+    x509_node subject;
+    x509_node subpubkey;
+
+    x509_node signalg;
+    x509_node sign;
+}
+x509_raw;
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to read in DHM parameters, a certificate, CRL or private RSA key
+ * \{
+ */
+
+/** \ingroup x509_module */
+/**
+ * \brief          Parse one or more certificates and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the certificate data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Load one or more certificates and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param path     filename to read the certificates from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_crtfile( x509_cert *chain, const char *path );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Parse one or more CRLs and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param buf      buffer holding the CRL data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Load one or more CRLs and add them
+ *                 to the chained list
+ *
+ * \param chain    points to the start of the chain
+ * \param path     filename to read the CRLs from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_crlfile( x509_crl *chain, const char *path );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Parse a private RSA key
+ *
+ * \param rsa      RSA context to be initialized
+ * \param key      input buffer
+ * \param keylen   size of the buffer
+ * \param pwd      password for decryption (optional)
+ * \param pwdlen   size of the password
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_key( rsa_context *rsa,
+                   const unsigned char *key, size_t keylen,
+                   const unsigned char *pwd, size_t pwdlen );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Load and parse a private RSA key
+ *
+ * \param rsa      RSA context to be initialized
+ * \param path     filename to read the private key from
+ * \param password password to decrypt the file (can be NULL)
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_keyfile( rsa_context *rsa, const char *path,
+                       const char *password );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Parse a public RSA key
+ *
+ * \param rsa      RSA context to be initialized
+ * \param key      input buffer
+ * \param keylen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_public_key( rsa_context *rsa,
+                   const unsigned char *key, size_t keylen );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Load and parse a public RSA key
+ *
+ * \param rsa      RSA context to be initialized
+ * \param path     filename to read the private key from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_public_keyfile( rsa_context *rsa, const char *path );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param dhmin    input buffer
+ * \param dhminlen size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Load and parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param path     filename to read the DHM Parameters from
+ *
+ * \return         0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_dhmfile( dhm_context *dhm, const char *path );
+
+/** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */
+
+
+
+/**
+ * \brief          Store the certificate DN in printable form into buf;
+ *                 no more than size characters will be written.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param dn       The X509 name to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn );
+
+/**
+ * \brief          Store the certificate serial in printable form into buf;
+ *                 no more than size characters will be written.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param serial   The X509 serial to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial );
+
+/**
+ * \brief          Returns an informational string about the
+ *                 certificate.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param crt      The X509 certificate to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509parse_cert_info( char *buf, size_t size, const char *prefix,
+                         const x509_cert *crt );
+
+/**
+ * \brief          Returns an informational string about the
+ *                 CRL.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param prefix   A line prefix
+ * \param crl      The X509 CRL to represent
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509parse_crl_info( char *buf, size_t size, const char *prefix,
+                        const x509_crl *crl );
+
+/**
+ * \brief          Give an known OID, return its descriptive string.
+ *
+ * \param oid      buffer containing the oid
+ *
+ * \return         Return a string if the OID is known,
+ *                 or NULL otherwise.
+ */
+const char *x509_oid_get_description( x509_buf *oid );
+
+/*
+ * \brief          Give an OID, return a string version of its OID number.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param oid      Buffer containing the OID
+ *
+ * \return         The amount of data written to the buffer, or -1 in
+ *                 case of an error.
+ */
+int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid );
+
+/**
+ * \brief          Check a given x509_time against the system time and check
+ *                 if it is valid.
+ *
+ * \param time     x509_time to check
+ *
+ * \return         Return 0 if the x509_time is still valid,
+ *                 or 1 otherwise.
+ */
+int x509parse_time_expired( const x509_time *time );
+
+/**
+ * \name Functions to verify a certificate
+ * \{
+ */
+/** \ingroup x509_module */
+/**
+ * \brief          Verify the certificate signature
+ *
+ * \param crt      a certificate to be verified
+ * \param trust_ca the trusted CA chain
+ * \param ca_crl   the CRL chain for trusted CA's
+ * \param cn       expected Common Name (can be set to
+ *                 NULL if the CN must not be verified)
+ * \param flags    result of the verification
+ * \param f_vrfy   verification function
+ * \param p_vrfy   verification parameter
+ *
+ * \return         0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
+ *                 in which case *flags will have one or more of
+ *                 the following values set:
+ *                      BADCERT_EXPIRED --
+ *                      BADCERT_REVOKED --
+ *                      BADCERT_CN_MISMATCH --
+ *                      BADCERT_NOT_TRUSTED
+ *
+ * \note           TODO: add two arguments, depth and crl
+ */
+int x509parse_verify( x509_cert *crt,
+                      x509_cert *trust_ca,
+                      x509_crl *ca_crl,
+                      const char *cn, int *flags,
+                      int (*f_vrfy)(void *, x509_cert *, int, int),
+                      void *p_vrfy );
+
+/**
+ * \brief          Verify the certificate signature
+ *
+ * \param crt      a certificate to be verified
+ * \param crl      the CRL to verify against
+ *
+ * \return         1 if the certificate is revoked, 0 otherwise
+ *
+ */
+int x509parse_revoked( const x509_cert *crt, const x509_crl *crl );
+
+/** \} name Functions to verify a certificate */
+
+
+
+/**
+ * \name Functions to clear a certificate, CRL or private RSA key 
+ * \{
+ */
+/** \ingroup x509_module */
+/**
+ * \brief          Unallocate all certificate data
+ *
+ * \param crt      Certificate chain to free
+ */
+void x509_free( x509_cert *crt );
+
+/** \ingroup x509_module */
+/**
+ * \brief          Unallocate all CRL data
+ *
+ * \param crl      CRL chain to free
+ */
+void x509_crl_free( x509_crl *crl );
+
+/** \} name Functions to clear a certificate, CRL or private RSA key */
+
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int x509_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509.h */

+ 111 - 0
thirdparty/PolarSSL/include/polarssl/xtea.h

@@ -0,0 +1,111 @@
+/**
+ * \file xtea.h
+ *
+ * \brief XTEA block cipher (32-bit)
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_XTEA_H
+#define POLARSSL_XTEA_H
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define XTEA_ENCRYPT     1
+#define XTEA_DECRYPT     0
+
+#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH             -0x0028  /**< The data input has an invalid length. */
+
+/**
+ * \brief          XTEA context structure
+ */
+typedef struct
+{
+    uint32_t k[4];       /*!< key */
+}
+xtea_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          XTEA key schedule
+ *
+ * \param ctx      XTEA context to be initialized
+ * \param key      the secret key
+ */
+void xtea_setup( xtea_context *ctx, unsigned char key[16] );
+
+/**
+ * \brief          XTEA cipher function
+ *
+ * \param ctx      XTEA context
+ * \param mode     XTEA_ENCRYPT or XTEA_DECRYPT
+ * \param input    8-byte input block
+ * \param output   8-byte output block
+ *
+ * \return         0 if successful
+ */
+int xtea_crypt_ecb( xtea_context *ctx,
+                    int mode,
+                    unsigned char input[8],
+                    unsigned char output[8] );
+
+/**
+ * \brief          XTEA CBC cipher function
+ *
+ * \param ctx      XTEA context
+ * \param mode     XTEA_ENCRYPT or XTEA_DECRYPT
+ * \param length   the length of input, multiple of 8
+ * \param iv       initialization vector for CBC mode
+ * \param input    input block
+ * \param output   output block
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0
+ */
+int xtea_crypt_cbc( xtea_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    unsigned char *input,
+                    unsigned char *output);
+
+/*
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int xtea_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* xtea.h */

+ 52 - 0
thirdparty/PolarSSL/library/CMakeLists.txt

@@ -0,0 +1,52 @@
+OPTION(USE_SHARED_POLARSSL_LIBRARY "Build PolarSSL as a shared library." OFF)
+
+set(src
+     aes.c
+     arc4.c
+     base64.c
+     bignum.c
+     camellia.c
+     certs.c
+     cipher.c
+     cipher_wrap.c
+     debug.c
+     des.c
+     dhm.c
+     error.c
+     havege.c
+     md.c
+     md_wrap.c
+     md2.c
+     md4.c
+     md5.c
+     net.c
+     padlock.c
+     pem.c
+     pkcs11.c
+     rsa.c
+     sha1.c
+     sha2.c
+     sha4.c
+     ssl_cli.c 
+     ssl_srv.c 
+     ssl_tls.c
+     timing.c
+     version.c
+     x509parse.c
+     xtea.c
+)
+
+if(NOT USE_SHARED_POLARSSL_LIBRARY)
+
+add_library(polarssl STATIC ${src})
+
+else(NOT USE_SHARED_POLARSSL_LIBRARY)
+
+ADD_LIBRARY(polarssl SHARED ${src})
+SET_TARGET_PROPERTIES(polarssl PROPERTIES VERSION 1.0.0 SOVERSION 0)
+
+endif(NOT USE_SHARED_POLARSSL_LIBRARY)
+
+INSTALL(TARGETS polarssl
+        DESTINATION ${LIB_INSTALL_DIR}
+        PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)

+ 69 - 0
thirdparty/PolarSSL/library/Makefile

@@ -0,0 +1,69 @@
+
+# Also see "include/polarssl/config.h"
+
+CFLAGS	+= -I../include -D_FILE_OFFSET_BITS=64 -Wall -W -Wdeclaration-after-statement
+OFLAGS	= -O
+
+# MicroBlaze specific options:
+# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift
+
+# To compile on Plan9:
+# CFLAGS += -D_BSD_EXTENSION
+
+# To compile as a shared library:
+# CFLAGS += -fPIC
+
+DLEXT=so
+# OSX shared library extension:
+# DLEXT=dylib
+
+# Windows shared library extension:
+# DLEXT=dll
+
+OBJS=	aes.o		arc4.o		base64.o	\
+		bignum.o	camellia.o	certs.o		\
+		cipher.o	cipher_wrap.o	debug.o	\
+		des.o		dhm.o		havege.o	\
+		error.o \
+		md.o		md_wrap.o	md2.o		\
+		md4.o		md5.o		net.o		\
+		padlock.o	pem.o		pkcs11.o	\
+		rsa.o		sha1.o		sha2.o		\
+		sha4.o		ssl_cli.o	ssl_srv.o	\
+		ssl_tls.o	timing.o	version.o	\
+		x509parse.o	xtea.o
+	
+
+.SILENT:
+
+all: static
+
+static: libpolarssl.a
+
+shared: libpolarssl.$(DLEXT)
+
+libpolarssl.a: $(OBJS)
+	echo "  AR    $@"
+	$(AR) r $@ $(OBJS)
+	echo "  RL    $@"
+	$(AR) s $@
+
+libpolarssl.so: libpolarssl.a
+	echo "  LD    $@"
+	$(CC) ${LDFLAGS} -shared -Wl,-soname,$@ -o $@ $(OBJS)
+
+libpolarssl.dylib: libpolarssl.a
+	echo "  LD    $@"
+	$(CC) ${LDFLAGS} -dynamiclib -o $@ $(OBJS)
+
+libpolarssl.dll: libpolarssl.a 
+	echo "  LD    $@" 
+	$(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS) -lws2_32 -lwinmm -lgdi32 
+
+.c.o:
+	echo "  CC    $<"
+	$(CC) $(CFLAGS) $(OFLAGS) -c $<
+
+clean:
+	rm -f *.o libpolarssl.*
+

+ 1822 - 0
thirdparty/PolarSSL/library/aes.c

@@ -0,0 +1,1822 @@
+/*
+ *  FIPS-197 compliant AES implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+/* Note: This file has been modified by ST's MCD Application Team, to support 
+   the hardware crypto engine embedded in STM32F417xx */
+
+#include "config.h"
+
+#if defined(POLARSSL_AES_C)
+
+#include "main.h"
+#include "polarssl/aes.h"
+#include "polarssl/padlock.h"
+
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+CRYP_InitTypeDef AES_CRYP_InitStructure; 
+CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; 
+CRYP_IVInitTypeDef AES_CRYP_IVInitStructure;
+
+#else /* use SW Crypto */
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_ULONG_LE
+#define GET_ULONG_LE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ]       )        \
+        | ( (unsigned long) (b)[(i) + 1] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 2] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 3] << 24 );       \
+}
+#endif
+
+#ifndef PUT_ULONG_LE
+#define PUT_ULONG_LE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+#if defined(POLARSSL_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[256] =
+{
+    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+    0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+    0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+    0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+    0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+    0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+    0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+    0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+    0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+    0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+    0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+    0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+    V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+    V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+    V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+    V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+    V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+    V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+    V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+    V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+    V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+    V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+    V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+    V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+    V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+    V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+    V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+    V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+    V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+    V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+    V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+    V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+    V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+    V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+    V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+    V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+    V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+    V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+    V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+    V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+    V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+    V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+    V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+    V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+    V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+    V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+    V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+    V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+    V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+    V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+    V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+    V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+    V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+    V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+    V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+    V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+    V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+    V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+    V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+    V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+    V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+    V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+    V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+    V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+    V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+    V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+    V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+    V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+    V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+    V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+    V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+    V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+    V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+    V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+    V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+    V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const unsigned long FT0[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const unsigned long FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const unsigned long FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const unsigned long FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[256] =
+{
+    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+    0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+    0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+    0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+    0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+    0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+    0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+    0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+    0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+    0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+    0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+    0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+    0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+    0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+    0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+    0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+    0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ */
+#define RT \
+\
+    V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
+    V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
+    V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
+    V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
+    V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
+    V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
+    V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
+    V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
+    V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
+    V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
+    V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
+    V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
+    V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
+    V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
+    V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
+    V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
+    V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
+    V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
+    V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
+    V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
+    V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
+    V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
+    V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
+    V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
+    V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
+    V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
+    V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
+    V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
+    V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
+    V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
+    V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
+    V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
+    V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
+    V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
+    V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
+    V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
+    V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
+    V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
+    V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
+    V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
+    V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
+    V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
+    V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
+    V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
+    V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
+    V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
+    V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
+    V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
+    V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
+    V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
+    V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
+    V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
+    V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
+    V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
+    V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
+    V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
+    V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
+    V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
+    V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
+    V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
+    V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
+    V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
+    V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
+    V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const unsigned long RT0[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const unsigned long RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const unsigned long RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const unsigned long RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const unsigned long RCON[10] =
+{
+    0x00000001, 0x00000002, 0x00000004, 0x00000008,
+    0x00000010, 0x00000020, 0x00000040, 0x00000080,
+    0x0000001B, 0x00000036
+};
+
+#else
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static unsigned long FT0[256]; 
+static unsigned long FT1[256]; 
+static unsigned long FT2[256]; 
+static unsigned long FT3[256]; 
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static unsigned long RT0[256];
+static unsigned long RT1[256];
+static unsigned long RT2[256];
+static unsigned long RT3[256];
+
+/*
+ * Round constants
+ */
+static unsigned long RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+    int i, x, y, z;
+    int pow[256];
+    int log[256];
+
+    /*
+     * compute pow and log tables over GF(2^8)
+     */
+    for( i = 0, x = 1; i < 256; i++ )
+    {
+        pow[i] = x;
+        log[x] = i;
+        x = ( x ^ XTIME( x ) ) & 0xFF;
+    }
+
+    /*
+     * calculate the round constants
+     */
+    for( i = 0, x = 1; i < 10; i++ )
+    {
+        RCON[i] = (unsigned long) x;
+        x = XTIME( x ) & 0xFF;
+    }
+
+    /*
+     * generate the forward and reverse S-boxes
+     */
+    FSb[0x00] = 0x63;
+    RSb[0x63] = 0x00;
+
+    for( i = 1; i < 256; i++ )
+    {
+        x = pow[255 - log[i]];
+
+        y  = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        x ^= y ^ 0x63;
+
+        FSb[i] = (unsigned char) x;
+        RSb[x] = (unsigned char) i;
+    }
+
+    /*
+     * generate the forward and reverse tables
+     */
+    for( i = 0; i < 256; i++ )
+    {
+        x = FSb[i];
+        y = XTIME( x ) & 0xFF;
+        z =  ( y ^ x ) & 0xFF;
+
+        FT0[i] = ( (unsigned long) y       ) ^
+                 ( (unsigned long) x <<  8 ) ^
+                 ( (unsigned long) x << 16 ) ^
+                 ( (unsigned long) z << 24 );
+
+        FT1[i] = ROTL8( FT0[i] );
+        FT2[i] = ROTL8( FT1[i] );
+        FT3[i] = ROTL8( FT2[i] );
+
+        x = RSb[i];
+
+        RT0[i] = ( (unsigned long) MUL( 0x0E, x )       ) ^
+                 ( (unsigned long) MUL( 0x09, x ) <<  8 ) ^
+                 ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^
+                 ( (unsigned long) MUL( 0x0B, x ) << 24 );
+
+        RT1[i] = ROTL8( RT0[i] );
+        RT2[i] = ROTL8( RT1[i] );
+        RT3[i] = ROTL8( RT2[i] );
+    }
+}
+
+#endif
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+
+/*
+ * AES key schedule (encryption)
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  switch( keysize )
+  {
+    case 128:
+      ctx->nr = 10;
+      memcpy(ctx->aes_enc_key, key, 16);
+      break;
+    case 192: 
+      ctx->nr = 12;
+      memcpy(ctx->aes_enc_key, key, 24);
+      break;
+    case 256:
+      ctx->nr = 14;
+      memcpy(ctx->aes_enc_key, key, 32); 
+      break;
+   default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+  }
+  return(0);
+
+#else /* use SW Crypto */
+
+    unsigned int i;
+    unsigned long *RK;
+
+#if !defined(POLARSSL_AES_ROM_TABLES)
+    if( aes_init_done == 0 )
+    {
+        aes_gen_tables();
+        aes_init_done = 1;
+    }
+#endif
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 10; break;
+        case 192: ctx->nr = 12; break;
+        case 256: ctx->nr = 14; break;
+        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+#if defined(PADLOCK_ALIGN16)
+    ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+#else
+    ctx->rk = RK = ctx->buf;
+#endif
+
+    for( i = 0; i < (keysize >> 5); i++ )
+    {
+        GET_ULONG_LE( RK[i], key, i << 2 );
+    }
+
+    switch( ctx->nr )
+    {
+        case 10:
+
+            for( i = 0; i < 10; i++, RK += 4 )
+            {
+                RK[4]  = RK[0] ^ RCON[i] ^
+                ( (unsigned long) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( RK[3]       ) & 0xFF ] << 24 );
+
+                RK[5]  = RK[1] ^ RK[4];
+                RK[6]  = RK[2] ^ RK[5];
+                RK[7]  = RK[3] ^ RK[6];
+            }
+            break;
+
+        case 12:
+
+            for( i = 0; i < 8; i++, RK += 6 )
+            {
+                RK[6]  = RK[0] ^ RCON[i] ^
+                ( (unsigned long) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( RK[5]       ) & 0xFF ] << 24 );
+
+                RK[7]  = RK[1] ^ RK[6];
+                RK[8]  = RK[2] ^ RK[7];
+                RK[9]  = RK[3] ^ RK[8];
+                RK[10] = RK[4] ^ RK[9];
+                RK[11] = RK[5] ^ RK[10];
+            }
+            break;
+
+        case 14:
+
+            for( i = 0; i < 7; i++, RK += 8 )
+            {
+                RK[8]  = RK[0] ^ RCON[i] ^
+                ( (unsigned long) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( RK[7]       ) & 0xFF ] << 24 );
+
+                RK[9]  = RK[1] ^ RK[8];
+                RK[10] = RK[2] ^ RK[9];
+                RK[11] = RK[3] ^ RK[10];
+
+                RK[12] = RK[4] ^
+                ( (unsigned long) FSb[ ( RK[11]       ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+                RK[13] = RK[5] ^ RK[12];
+                RK[14] = RK[6] ^ RK[13];
+                RK[15] = RK[7] ^ RK[14];
+            }
+            break;
+
+        default:
+
+            break;
+    }
+
+    return( 0 );
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+}
+
+/*
+ * AES key schedule (decryption)
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  switch( keysize )
+  {
+    case 128: 
+      ctx->nr = 10;
+      memcpy(&(ctx->aes_dec_key), key, 16);
+      break;
+    case 192: 
+      ctx->nr = 12;
+      memcpy(ctx->aes_dec_key, key, 24);
+      break;
+    case 256:
+      ctx->nr = 14;
+      memcpy(ctx->aes_dec_key, key, 32); 
+      break;
+    default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+  }
+  return( 0 );
+
+#else /* use SW Crypto */
+
+    int i, j;
+    aes_context cty;
+    unsigned long *RK;
+    unsigned long *SK;
+    int ret;
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 10; break;
+        case 192: ctx->nr = 12; break;
+        case 256: ctx->nr = 14; break;
+        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+#if defined(PADLOCK_ALIGN16)
+    ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+#else
+    ctx->rk = RK = ctx->buf;
+#endif
+
+    ret = aes_setkey_enc( &cty, key, keysize );
+    if( ret != 0 )
+        return( ret );
+
+    SK = cty.rk + cty.nr * 4;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+    {
+        for( j = 0; j < 4; j++, SK++ )
+        {
+            *RK++ = RT0[ FSb[ ( *SK       ) & 0xFF ] ] ^
+                    RT1[ FSb[ ( *SK >>  8 ) & 0xFF ] ] ^
+                    RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
+                    RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+        }
+    }
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    memset( &cty, 0, sizeof( aes_context ) );
+
+    return( 0 );
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+}
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ FT0[ ( Y0       ) & 0xFF ] ^   \
+                 FT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ FT0[ ( Y1       ) & 0xFF ] ^   \
+                 FT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y0 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ FT0[ ( Y2       ) & 0xFF ] ^   \
+                 FT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ FT0[ ( Y3       ) & 0xFF ] ^   \
+                 FT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y2 >> 24 ) & 0xFF ];    \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ RT0[ ( Y0       ) & 0xFF ] ^   \
+                 RT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ RT0[ ( Y1       ) & 0xFF ] ^   \
+                 RT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y2 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ RT0[ ( Y2       ) & 0xFF ] ^   \
+                 RT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ RT0[ ( Y3       ) & 0xFF ] ^   \
+                 RT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y0 >> 24 ) & 0xFF ];    \
+}
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int aes_crypt_ecb( aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  int NR; /* Number of rounds */
+  unsigned char *ENC_KEY, *DEC_KEY; /* AES encryption/decryption key */
+  
+  /* number of rounds */
+  NR = ctx->nr;
+  
+  /* Encryption key */
+  ENC_KEY = ctx->aes_enc_key;
+  
+  /* Decryption key */
+  DEC_KEY = ctx->aes_dec_key;
+  
+  /* Crypto structures initialisation*/
+  CRYP_StructInit(&AES_CRYP_InitStructure);  
+  CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
+    
+  /*------------------ AES Decryption ------------------*/       
+  if(mode == AES_DECRYPT) /* AES decryption */
+  {
+    /* Deinitializes the CRYP peripheral */
+    CRYP_DeInit();
+	  
+    /* Flush IN/OUT FIFOs */
+    CRYP_FIFOFlush();
+    
+    /* Crypto Init for Key preparation for decryption process */ 
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_32b;
+    switch( NR )
+    {
+      case 10: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_128b; break;
+      case 12: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b; break;
+      case 14: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b; break;
+      default : break;
+    }
+    CRYP_Init(&AES_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    switch( NR )
+    {
+      case 10: 
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&DEC_KEY[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&DEC_KEY[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&DEC_KEY[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&DEC_KEY[12]);
+        break;
+
+      case 12: 
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&DEC_KEY[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&DEC_KEY[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&DEC_KEY[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&DEC_KEY[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&DEC_KEY[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&DEC_KEY[20]);
+        break;
+   
+      case 14:
+        AES_CRYP_KeyInitStructure.CRYP_Key0Left = __REV(*(uint32_t*)&DEC_KEY[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key0Right= __REV(*(uint32_t*)&DEC_KEY[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&DEC_KEY[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&DEC_KEY[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&DEC_KEY[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&DEC_KEY[20]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&DEC_KEY[24]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&DEC_KEY[28]);
+        break;
+      default : break; 
+    }
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+
+    /* Enable Crypto processor */
+    CRYP_Cmd( ENABLE );
+
+    /* Wait until the Busy flag is reset */
+    while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET);
+
+    /* Crypto Init for decryption process */  
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    switch( NR )
+    {
+      case 10: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_128b; break;
+      case 12: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b; break;
+      case 14: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b; break;
+      default : break;
+    }
+    CRYP_Init(&AES_CRYP_InitStructure);
+
+    /* Flush IN/OUT FIFOs */
+    CRYP_FIFOFlush();
+      
+    /* Write the input block in the IN FIFO */
+    CRYP_DataIn(*(uint32_t*)&input[0]);
+    CRYP_DataIn(*(uint32_t*)&input[4]);
+    CRYP_DataIn(*(uint32_t*)&input[8]);
+    CRYP_DataIn(*(uint32_t*)&input[12]); 
+
+    /* Enable Crypto processor */
+    CRYP_Cmd( ENABLE );
+
+    /* Wait until the complete message has been processed */ 
+    while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET);
+   
+    /* Read the output block from the OUT FIFO */
+    *(uint32_t*)&output[0] = CRYP_DataOut();
+    *(uint32_t*)&output[4] = CRYP_DataOut();
+    *(uint32_t*)&output[8] = CRYP_DataOut();
+    *(uint32_t*)&output[12] = CRYP_DataOut();
+
+    /* Disable Crypto processor */
+    CRYP_Cmd(DISABLE);
+  }
+  /*------------------ AES Encryption ------------------*/
+  else /* AES encryption */
+  {
+    /* Deinitializes the CRYP peripheral */
+    CRYP_DeInit();
+    
+    /* Key Initialisation */
+    switch( NR )
+    {
+      case 10: 
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&ENC_KEY[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&ENC_KEY[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&ENC_KEY[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&ENC_KEY[12]);
+        break;
+
+      case 12: 
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&ENC_KEY[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&ENC_KEY[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&ENC_KEY[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&ENC_KEY[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&ENC_KEY[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&ENC_KEY[20]);
+        break;
+   
+      case 14:
+        AES_CRYP_KeyInitStructure.CRYP_Key0Left = __REV(*(uint32_t*)&ENC_KEY[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key0Right= __REV(*(uint32_t*)&ENC_KEY[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&ENC_KEY[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&ENC_KEY[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&ENC_KEY[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&ENC_KEY[20]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&ENC_KEY[24]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&ENC_KEY[28]);
+        break;
+      default : break;
+    }
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+  
+    /* Crypto Init for Encryption process */      
+    AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    switch( NR )
+    {
+      case 10: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_128b; break;
+      case 12: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b; break;
+      case 14: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b; break;
+      default : break;
+    }
+    CRYP_Init(&AES_CRYP_InitStructure);
+   
+    /* Flush IN/OUT FIFOs */
+    CRYP_FIFOFlush();
+
+    /* Write the input block in the IN FIFO */
+    CRYP_DataIn(*(uint32_t*)&input[0]);
+    CRYP_DataIn(*(uint32_t*)&input[4]);
+    CRYP_DataIn(*(uint32_t*)&input[8]);
+    CRYP_DataIn(*(uint32_t*)&input[12]);  
+
+    /* Enable Crypto processor */
+    CRYP_Cmd(ENABLE);
+
+    /* Wait until the complete message has been processed */ 
+    while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY)!= RESET);
+    
+    /* Read the output block from the output FIFO */
+    *(uint32_t*)&output[0] = CRYP_DataOut();
+    *(uint32_t*)&output[4] = CRYP_DataOut();
+    *(uint32_t*)&output[8] = CRYP_DataOut();
+    *(uint32_t*)&output[12] = CRYP_DataOut();
+  
+    /* Disable Crypto */
+    CRYP_Cmd(DISABLE);
+  }
+
+#else /* use SW Crypto */
+    int i;
+    unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+    if( padlock_supports( PADLOCK_ACE ) )
+    {
+        if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )
+            return( 0 );
+
+        // If padlock data misaligned, we just fall back to
+        // unaccelerated mode
+        //
+    }
+#endif
+
+    RK = ctx->rk;
+
+    GET_ULONG_LE( X0, input,  0 ); X0 ^= *RK++;
+    GET_ULONG_LE( X1, input,  4 ); X1 ^= *RK++;
+    GET_ULONG_LE( X2, input,  8 ); X2 ^= *RK++;
+    GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++;
+
+    if( mode == AES_DECRYPT )
+    {
+        for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+        {
+            AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+            AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        }
+
+        AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+        X0 = *RK++ ^ \
+                ( (unsigned long) RSb[ ( Y0       ) & 0xFF ]       ) ^
+                ( (unsigned long) RSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+        X1 = *RK++ ^ \
+                ( (unsigned long) RSb[ ( Y1       ) & 0xFF ]       ) ^
+                ( (unsigned long) RSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+        X2 = *RK++ ^ \
+                ( (unsigned long) RSb[ ( Y2       ) & 0xFF ]       ) ^
+                ( (unsigned long) RSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+        X3 = *RK++ ^ \
+                ( (unsigned long) RSb[ ( Y3       ) & 0xFF ]       ) ^
+                ( (unsigned long) RSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+    }
+    else /* AES_ENCRYPT */
+    {
+        for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+        {
+            AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+            AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        }
+
+        AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+        X0 = *RK++ ^ \
+                ( (unsigned long) FSb[ ( Y0       ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+        X1 = *RK++ ^ \
+                ( (unsigned long) FSb[ ( Y1       ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+        X2 = *RK++ ^ \
+                ( (unsigned long) FSb[ ( Y2       ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+        X3 = *RK++ ^ \
+                ( (unsigned long) FSb[ ( Y3       ) & 0xFF ]       ) ^
+                ( (unsigned long) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+    }
+
+    PUT_ULONG_LE( X0, output,  0 );
+    PUT_ULONG_LE( X1, output,  4 );
+    PUT_ULONG_LE( X2, output,  8 );
+    PUT_ULONG_LE( X3, output, 12 );
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */ 
+    return( 0 );
+}
+
+/*
+ * AES-CBC buffer encryption/decryption
+ */
+int aes_crypt_cbc( aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  int nround; /* Number of rounds */
+  unsigned char *enc_key, *dec_key; /* AES encryption/decryption key */
+  
+  /* Number of rounds */
+  nround = ctx->nr;
+  
+  /* Encryption key */
+  enc_key = ctx->aes_enc_key;
+  
+  /* Decryption key */
+  dec_key = ctx->aes_dec_key;
+
+  /* Crypto structures initialisation*/
+  CRYP_StructInit(&AES_CRYP_InitStructure);  
+  CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure);
+  CRYP_IVStructInit(&AES_CRYP_IVInitStructure);
+    
+  /*------------------ AES Decryption ------------------*/       
+  if(mode == AES_DECRYPT) /* AES Decryption */
+  {
+    /* Deinitializes the CRYP peripheral */
+    CRYP_DeInit();
+	  
+    /* Flush IN/OUT FIFOs */
+    CRYP_FIFOFlush();
+
+    /* Crypto Init for Key preparation for decryption process */ 
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_32b;
+    switch(nround)
+    {
+      case 10: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_128b; break;
+      case 12: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b; break;
+      case 14: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b; break;
+      default : break;
+    }
+    CRYP_Init(&AES_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    switch(nround)
+    {
+      case 10: 
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&dec_key[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&dec_key[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&dec_key[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&dec_key[12]);
+        break;
+
+      case 12: 
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&dec_key[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&dec_key[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&dec_key[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&dec_key[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&dec_key[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&dec_key[20]);
+        break;
+   
+      case 14:
+        AES_CRYP_KeyInitStructure.CRYP_Key0Left = __REV(*(uint32_t*)&dec_key[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key0Right= __REV(*(uint32_t*)&dec_key[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&dec_key[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&dec_key[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&dec_key[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&dec_key[20]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&dec_key[24]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&dec_key[28]);
+        break;
+      default : break; 
+    }
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+
+    /* Enable Crypto processor */
+    CRYP_Cmd(ENABLE);
+
+   /* Wait until the Busy flag is reset */
+    while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET);
+
+    /* Crypto Init for decryption process */  
+    AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    switch(nround)
+    {
+      case 10: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_128b; break;
+      case 12: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b; break;
+      case 14: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b; break;
+      default : break;
+    }
+    CRYP_Init(&AES_CRYP_InitStructure);
+
+    /* CRYP Initialization Vectors */
+    AES_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)&iv[0]);
+    AES_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)&iv[4]);
+    AES_CRYP_IVInitStructure.CRYP_IV1Left = __REV(*(uint32_t*)&iv[8]);
+    AES_CRYP_IVInitStructure.CRYP_IV1Right= __REV(*(uint32_t*)&iv[12]);
+    CRYP_IVInit(&AES_CRYP_IVInitStructure);
+
+    while(length > 0)
+    {
+      /* Update the initialization Vector */
+      memcpy(iv, input, 16);
+
+      /* Flush IN/OUT FIFOs */
+      CRYP_FIFOFlush();
+
+      /* Write the input block in the IN FIFO */
+      CRYP_DataIn(*(uint32_t*)&input[0]);
+      CRYP_DataIn(*(uint32_t*)&input[4]);
+      CRYP_DataIn(*(uint32_t*)&input[8]);
+      CRYP_DataIn(*(uint32_t*)&input[12]); 
+
+      /* Enable Crypto processor */
+      CRYP_Cmd( ENABLE );
+
+      /* Wait until the complete message has been processed */ 
+      while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET);
+   
+      /* Read the output block from the OUT FIFO */
+      *(uint32_t*)&output[0] = CRYP_DataOut();
+      *(uint32_t*)&output[4] = CRYP_DataOut();
+      *(uint32_t*)&output[8] = CRYP_DataOut();
+      *(uint32_t*)&output[12] = CRYP_DataOut();
+    
+      input  += 16;
+      output += 16;
+      length -= 16;    
+    }
+    /* Disable Crypto processor */
+    CRYP_Cmd(DISABLE);
+  }
+  /*------------------ AES Encryption ------------------*/
+  else /* AES Encryption */
+  {
+    /* Deinitializes the CRYP peripheral */
+    CRYP_DeInit();
+
+    /* Key Initialisation */
+    switch(nround)
+    {
+      case 10: 
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&enc_key[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&enc_key[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&enc_key[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&enc_key[12]);
+        break;
+
+      case 12: 
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&enc_key[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&enc_key[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&enc_key[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&enc_key[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&enc_key[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&enc_key[20]);
+        break;
+   
+      case 14:
+        AES_CRYP_KeyInitStructure.CRYP_Key0Left = __REV(*(uint32_t*)&enc_key[0]);
+        AES_CRYP_KeyInitStructure.CRYP_Key0Right= __REV(*(uint32_t*)&enc_key[4]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&enc_key[8]);
+        AES_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&enc_key[12]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&enc_key[16]);
+        AES_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&enc_key[20]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&enc_key[24]);
+        AES_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&enc_key[28]);
+        break;
+      default : break;
+    }
+    CRYP_KeyInit(&AES_CRYP_KeyInitStructure);
+    
+    /* Crypto Init for Encryption process */     
+    AES_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+    AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC;
+    AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    switch(nround)
+    {
+      case 10: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_128b; break;
+      case 12: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_192b; break;
+      case 14: AES_CRYP_InitStructure.CRYP_KeySize  = CRYP_KeySize_256b; break;
+      default : break;
+    }
+    CRYP_Init(&AES_CRYP_InitStructure);
+    
+    /* Initialization Vectors */
+    AES_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)&iv[0]);
+    AES_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)&iv[4]);
+    AES_CRYP_IVInitStructure.CRYP_IV1Left = __REV(*(uint32_t*)&iv[8]);
+    AES_CRYP_IVInitStructure.CRYP_IV1Right= __REV(*(uint32_t*)&iv[12]);
+    CRYP_IVInit(&AES_CRYP_IVInitStructure);
+   
+    while(length > 0)
+    {   
+      /* Flush IN/OUT FIFOs */
+      CRYP_FIFOFlush();
+
+      /* Write the input block in the IN FIFO */
+      CRYP_DataIn(*(uint32_t*)&input[0]);
+      CRYP_DataIn(*(uint32_t*)&input[4]);
+      CRYP_DataIn(*(uint32_t*)&input[8]);
+      CRYP_DataIn(*(uint32_t*)&input[12]); 
+
+      /* Enable Crypto processor */
+      CRYP_Cmd( ENABLE );
+
+      /* Wait until the complete message has been processed */ 
+      while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET);
+   
+      /* Read the output block from the OUT FIFO */
+      *(uint32_t*)&output[0] = CRYP_DataOut();
+      *(uint32_t*)&output[4] = CRYP_DataOut();
+      *(uint32_t*)&output[8] = CRYP_DataOut();
+      *(uint32_t*)&output[12] = CRYP_DataOut();
+
+      /* Update the initialization Vector */
+      memcpy(iv, output, 16);
+
+      input  += 16;
+      output += 16;
+      length -= 16;    
+    }
+    /* Disable Crypto */
+    CRYP_Cmd(DISABLE);
+  }    
+
+#else /* use SW Crypto */
+
+    int i;
+    unsigned char temp[16];
+
+    if( length % 16 )
+        return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+    if( padlock_supports( PADLOCK_ACE ) )
+    {
+        if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
+            return( 0 );
+        
+        // If padlock data misaligned, we just fall back to
+        // unaccelerated mode
+        //
+    }
+#endif
+
+    if( mode == AES_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 16 );
+            aes_crypt_ecb( ctx, mode, input, output );
+
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+    else
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            aes_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */ 
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 buffer encryption/decryption
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c;
+    size_t n = *iv_off;
+
+    if( mode == AES_DECRYPT )
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+            c = *input++;
+            *output++ = (unsigned char)( c ^ iv[n] );
+            iv[n] = (unsigned char) c;
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+    else
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+
+    *iv_off = n;
+
+    return( 0 );
+}
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR buffer encryption/decryption
+ */
+int aes_crypt_ctr( aes_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c, i, cb;
+    size_t n = *nc_off;
+
+    while( length-- )
+    {
+        if( n == 0 ) {
+            aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
+
+            i = 15;
+            do {
+               nonce_counter[i]++;
+               cb = nonce_counter[i] == 0;
+            } while( i-- && cb );
+
+        }
+        c = *input++;
+        *output++ = (unsigned char)( c ^ stream_block[n] );
+
+        n = (n + 1) & 0x0F;
+    }
+
+    *nc_off = n;
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+    { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+      0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+    { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+      0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+    { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+      0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+    { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+      0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+    { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+      0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+    { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+      0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+    { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+      0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+    { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+      0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+    { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+      0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+    { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+      0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+    { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+      0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+    { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+      0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_cfb128_iv[16] =
+{
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+      0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+      0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+      0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+      0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+      0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+      0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+      0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+      0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+      0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+      0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+      0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+      0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+      0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+      0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+      0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+      0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+      0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+      0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+      0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+    { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+      0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+    { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+      0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+      0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+      0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+    { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+      0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+      0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+      0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+      0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+    { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int aes_self_test( int verbose )
+{
+    int i, j, u, v;
+    unsigned char key[32];
+    unsigned char buf[64];
+    unsigned char prv[16];
+    unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB)
+    size_t offset;
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    int len;
+    unsigned char nonce_counter[16];
+    unsigned char stream_block[16];
+#endif
+    aes_context ctx;
+
+    memset( key, 0, 32 );
+
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  AES-ECB-%3d (%s): ", 128 + u * 64,
+                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( buf, 0, 16 );
+
+        if( v == AES_DECRYPT )
+        {
+            aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                aes_crypt_ecb( &ctx, v, buf, buf );
+
+            if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                aes_crypt_ecb( &ctx, v, buf, buf );
+
+            if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    /*
+     * CBC mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  AES-CBC-%3d (%s): ", 128 + u * 64,
+                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( iv , 0, 16 );
+        memset( prv, 0, 16 );
+        memset( buf, 0, 16 );
+
+        if( v == AES_DECRYPT )
+        {
+            aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+            {
+                unsigned char tmp[16];
+
+                aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+                memcpy( tmp, prv, 16 );
+                memcpy( prv, buf, 16 );
+                memcpy( buf, tmp, 16 );
+            }
+
+            if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    /*
+     * CFB128 mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  AES-CFB128-%3d (%s): ", 128 + u * 64,
+                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  aes_test_cfb128_iv, 16 );
+        memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
+
+        offset = 0;
+        aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+        if( v == AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_cfb128_ct[u], 64 );
+            aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            memcpy( buf, aes_test_cfb128_pt, 64 );
+            aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    /*
+     * CTR mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  AES-CTR-128 (%s): ",
+                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+        memcpy( key, aes_test_ctr_key[u], 16 );
+
+        offset = 0;
+        aes_setkey_enc( &ctx, key, 128 );
+
+        if( v == AES_DECRYPT )
+        {
+            len = aes_test_ctr_len[u];
+            memcpy( buf, aes_test_ctr_ct[u], len );
+
+            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+            if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            len = aes_test_ctr_len[u];
+            memcpy( buf, aes_test_ctr_pt[u], len );
+
+            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+            if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 173 - 0
thirdparty/PolarSSL/library/arc4.c

@@ -0,0 +1,173 @@
+/*
+ *  An implementation of the ARCFOUR algorithm
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The ARCFOUR algorithm was publicly disclosed on 94/09.
+ *
+ *  http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_ARC4_C)
+
+#include "polarssl/arc4.h"
+
+/*
+ * ARC4 key schedule
+ */
+void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen )
+{
+    int i, j, a;
+    unsigned int k;
+    unsigned char *m;
+
+    ctx->x = 0;
+    ctx->y = 0;
+    m = ctx->m;
+
+    for( i = 0; i < 256; i++ )
+        m[i] = (unsigned char) i;
+
+    j = k = 0;
+
+    for( i = 0; i < 256; i++, k++ )
+    {
+        if( k >= keylen ) k = 0;
+
+        a = m[i];
+        j = ( j + a + key[k] ) & 0xFF;
+        m[i] = m[j];
+        m[j] = (unsigned char) a;
+    }
+}
+
+/*
+ * ARC4 cipher function
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+                unsigned char *output )
+{
+    int x, y, a, b;
+    size_t i;
+    unsigned char *m;
+
+    x = ctx->x;
+    y = ctx->y;
+    m = ctx->m;
+
+    for( i = 0; i < length; i++ )
+    {
+        x = ( x + 1 ) & 0xFF; a = m[x];
+        y = ( y + a ) & 0xFF; b = m[y];
+
+        m[x] = (unsigned char) b;
+        m[y] = (unsigned char) a;
+
+        output[i] = (unsigned char)
+            ( input[i] ^ m[(unsigned char)( a + b )] );
+    }
+
+    ctx->x = x;
+    ctx->y = y;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+/*
+ * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
+ *
+ * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
+ */
+static const unsigned char arc4_test_key[3][8] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_pt[3][8] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_ct[3][8] =
+{
+    { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
+    { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
+    { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
+};
+
+/*
+ * Checkup routine
+ */
+int arc4_self_test( int verbose )
+{
+    int i;
+    unsigned char ibuf[8];
+    unsigned char obuf[8];
+    arc4_context ctx;
+
+    for( i = 0; i < 3; i++ )
+    {
+        if( verbose != 0 )
+            printf( "  ARC4 test #%d: ", i + 1 );
+
+        memcpy( ibuf, arc4_test_pt[i], 8 );
+
+        arc4_setup( &ctx, (unsigned char *) arc4_test_key[i], 8 );
+        arc4_crypt( &ctx, 8, ibuf, obuf );
+
+        if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 258 - 0
thirdparty/PolarSSL/library/base64.c

@@ -0,0 +1,258 @@
+/*
+ *  RFC 1521 base64 encoding/decoding
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_BASE64_C)
+
+#include "polarssl/base64.h"
+
+static const unsigned char base64_enc_map[64] =
+{
+    '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', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
+     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
+    127,  64, 127, 127, 127,   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, 127, 127, 127, 127, 127, 127,  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, 127, 127, 127, 127, 127
+};
+
+/*
+ * Encode a buffer into base64 format
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, n;
+    int C1, C2, C3;
+    unsigned char *p;
+
+    if( slen == 0 )
+        return( 0 );
+
+    n = (slen << 3) / 6;
+
+    switch( (slen << 3) - (n * 6) )
+    {
+        case  2: n += 3; break;
+        case  4: n += 2; break;
+        default: break;
+    }
+
+    if( *dlen < n + 1 )
+    {
+        *dlen = n + 1;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+    n = (slen / 3) * 3;
+
+    for( i = 0, p = dst; i < n; i += 3 )
+    {
+        C1 = *src++;
+        C2 = *src++;
+        C3 = *src++;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
+        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+        *p++ = base64_enc_map[C3 & 0x3F];
+    }
+
+    if( i < slen )
+    {
+        C1 = *src++;
+        C2 = ((i + 1) < slen) ? *src++ : 0;
+
+        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+        if( (i + 1) < slen )
+             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+        else *p++ = '=';
+
+        *p++ = '=';
+    }
+
+    *dlen = p - dst;
+    *p = 0;
+
+    return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+                   const unsigned char *src, size_t slen )
+{
+    size_t i, j, n;
+    unsigned long x;
+    unsigned char *p;
+
+    for( i = j = n = 0; i < slen; i++ )
+    {
+        if( ( slen - i ) >= 2 &&
+            src[i] == '\r' && src[i + 1] == '\n' )
+            continue;
+
+        if( src[i] == '\n' )
+            continue;
+
+        if( src[i] == '=' && ++j > 2 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        if( base64_dec_map[src[i]] < 64 && j != 0 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+        n++;
+    }
+
+    if( n == 0 )
+        return( 0 );
+
+    n = ((n * 6) + 7) >> 3;
+
+    if( *dlen < n )
+    {
+        *dlen = n;
+        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+    }
+
+   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+   {
+        if( *src == '\r' || *src == '\n' )
+            continue;
+
+        j -= ( base64_dec_map[*src] == 64 );
+        x  = (x << 6) | ( base64_dec_map[*src] & 0x3F );
+
+        if( ++n == 4 )
+        {
+            n = 0;
+            if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+            if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
+            if( j > 2 ) *p++ = (unsigned char)( x       );
+        }
+    }
+
+    *dlen = p - dst;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+static const unsigned char base64_test_dec[64] =
+{
+    0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+    0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+    0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+    0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+    0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+    0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+    0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+    0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+    "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+    "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int base64_self_test( int verbose )
+{
+    size_t len;
+    unsigned char *src, buffer[128];
+
+    if( verbose != 0 )
+        printf( "  Base64 encoding test: " );
+
+    len = sizeof( buffer );
+    src = (unsigned char *) base64_test_dec;
+
+    if( base64_encode( buffer, &len, src, 64 ) != 0 ||
+         memcmp( base64_test_enc, buffer, 88 ) != 0 ) 
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n  Base64 decoding test: " );
+
+    len = sizeof( buffer );
+    src = (unsigned char *) base64_test_enc;
+
+    if( base64_decode( buffer, &len, src, 88 ) != 0 ||
+         memcmp( base64_test_dec, buffer, 64 ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 2097 - 0
thirdparty/PolarSSL/library/bignum.c

@@ -0,0 +1,2097 @@
+/*
+ *  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  This MPI implementation is based on:
+ *
+ *  http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ *  http://www.stillhq.com/extracted/gnupg-api/mpi/
+ *  http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "polarssl/bignum.h"
+#include "polarssl/bn_mul.h"
+
+#include <stdlib.h>
+
+#define ciL    (sizeof(t_uint))         /* chars in limb  */
+#define biL    (ciL << 3)               /* bits  in limb  */
+#define biH    (ciL << 2)               /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i)  (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+/*
+ * Initialize one MPI
+ */
+void mpi_init( mpi *X )
+{
+    if( X == NULL )
+        return;
+
+    X->s = 1;
+    X->n = 0;
+    X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mpi_free( mpi *X )
+{
+    if( X == NULL )
+        return;
+
+    if( X->p != NULL )
+    {
+        memset( X->p, 0, X->n * ciL );
+        free( X->p );
+    }
+
+    X->s = 1;
+    X->n = 0;
+    X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, size_t nblimbs )
+{
+    t_uint *p;
+
+    if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
+        return( 1 );
+
+    if( X->n < nblimbs )
+    {
+        if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
+            return( 1 );
+
+        memset( p, 0, nblimbs * ciL );
+
+        if( X->p != NULL )
+        {
+            memcpy( p, X->p, X->n * ciL );
+            memset( X->p, 0, X->n * ciL );
+            free( X->p );
+        }
+
+        X->n = nblimbs;
+        X->p = p;
+    }
+
+    return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, const mpi *Y )
+{
+    int ret;
+    size_t i;
+
+    if( X == Y )
+        return( 0 );
+
+    for( i = Y->n - 1; i > 0; i-- )
+        if( Y->p[i] != 0 )
+            break;
+    i++;
+
+    X->s = Y->s;
+
+    MPI_CHK( mpi_grow( X, i ) );
+
+    memset( X->p, 0, X->n * ciL );
+    memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+    mpi T;
+
+    memcpy( &T,  X, sizeof( mpi ) );
+    memcpy(  X,  Y, sizeof( mpi ) );
+    memcpy(  Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, t_sint z )
+{
+    int ret;
+
+    MPI_CHK( mpi_grow( X, 1 ) );
+    memset( X->p, 0, X->n * ciL );
+
+    X->p[0] = ( z < 0 ) ? -z : z;
+    X->s    = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mpi_get_bit( mpi *X, size_t pos )
+{
+    if( X->n * biL <= pos )
+        return( 0 );
+
+    return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
+{
+    int ret = 0;
+    size_t off = pos / biL;
+    size_t idx = pos % biL;
+
+    if( val != 0 && val != 1 )
+        return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
+        
+    if( X->n * biL <= pos )
+    {
+        if( val == 0 )
+            return ( 0 );
+
+        MPI_CHK( mpi_grow( X, off + 1 ) );
+    }
+
+    X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
+
+cleanup:
+    
+    return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+size_t mpi_lsb( const mpi *X )
+{
+    size_t i, j, count = 0;
+
+    for( i = 0; i < X->n; i++ )
+        for( j = 0; j < biL; j++, count++ )
+            if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+                return( count );
+
+    return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+size_t mpi_msb( const mpi *X )
+{
+    size_t i, j;
+
+    for( i = X->n - 1; i > 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+
+    for( j = biL; j > 0; j-- )
+        if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
+            break;
+
+    return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mpi_size( const mpi *X )
+{
+    return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( t_uint *d, int radix, char c )
+{
+    *d = 255;
+
+    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+    if( *d >= (t_uint) radix )
+        return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
+
+    return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mpi_read_string( mpi *X, int radix, const char *s )
+{
+    int ret;
+    size_t i, j, slen, n;
+    t_uint d;
+    mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &T );
+
+    slen = strlen( s );
+
+    if( radix == 16 )
+    {
+        n = BITS_TO_LIMBS( slen << 2 );
+
+        MPI_CHK( mpi_grow( X, n ) );
+        MPI_CHK( mpi_lset( X, 0 ) );
+
+        for( i = slen, j = 0; i > 0; i--, j++ )
+        {
+            if( i == 1 && s[i - 1] == '-' )
+            {
+                X->s = -1;
+                break;
+            }
+
+            MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
+            X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_lset( X, 0 ) );
+
+        for( i = 0; i < slen; i++ )
+        {
+            if( i == 0 && s[i] == '-' )
+            {
+                X->s = -1;
+                continue;
+            }
+
+            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+            MPI_CHK( mpi_mul_int( &T, X, radix ) );
+
+            if( X->s == 1 )
+            {
+                MPI_CHK( mpi_add_int( X, &T, d ) );
+            }
+            else
+            {
+                MPI_CHK( mpi_sub_int( X, &T, d ) );
+            }
+        }
+    }
+
+cleanup:
+
+    mpi_free( &T );
+
+    return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mpi *X, int radix, char **p )
+{
+    int ret;
+    t_uint r;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    MPI_CHK( mpi_mod_int( &r, X, radix ) );
+    MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
+
+    if( mpi_cmp_int( X, 0 ) != 0 )
+        MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+    if( r < 10 )
+        *(*p)++ = (char)( r + 0x30 );
+    else
+        *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
+{
+    int ret = 0;
+    size_t n;
+    char *p;
+    mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    n = mpi_msb( X );
+    if( radix >=  4 ) n >>= 1;
+    if( radix >= 16 ) n >>= 1;
+    n += 3;
+
+    if( *slen < n )
+    {
+        *slen = n;
+        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+    }
+
+    p = s;
+    mpi_init( &T );
+
+    if( X->s == -1 )
+        *p++ = '-';
+
+    if( radix == 16 )
+    {
+        int c;
+        size_t i, j, k;
+
+        for( i = X->n, k = 0; i > 0; i-- )
+        {
+            for( j = ciL; j > 0; j-- )
+            {
+                c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+
+                if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
+                    continue;
+
+                p += sprintf( p, "%02X", c );
+                k = 1;
+            }
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_copy( &T, X ) );
+
+        if( T.s == -1 )
+            T.s = 1;
+
+        MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+    }
+
+    *p++ = '\0';
+    *slen = p - s;
+
+cleanup:
+
+    mpi_free( &T );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Read X from an opened file
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin )
+{
+    t_uint d;
+    size_t slen;
+    char *p;
+    char s[1024];
+
+    memset( s, 0, sizeof( s ) );
+    if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+        return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+
+    slen = strlen( s );
+    if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+    if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+    p = s + slen;
+    while( --p >= s )
+        if( mpi_get_digit( &d, radix, *p ) != 0 )
+            break;
+
+    return( mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
+{
+    int ret;
+    size_t n, slen, plen;
+    char s[2048];
+
+    n = sizeof( s );
+    memset( s, 0, n );
+    n -= 2;
+
+    MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
+
+    if( p == NULL ) p = "";
+
+    plen = strlen( p );
+    slen = strlen( s );
+    s[slen++] = '\r';
+    s[slen++] = '\n';
+
+    if( fout != NULL )
+    {
+        if( fwrite( p, 1, plen, fout ) != plen ||
+            fwrite( s, 1, slen, fout ) != slen )
+            return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+    }
+    else
+        printf( "%s%s", p, s );
+
+cleanup:
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+    size_t i, j, n;
+
+    for( n = 0; n < buflen; n++ )
+        if( buf[n] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    for( i = buflen, j = 0; i > n; i--, j++ )
+        X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
+{
+    size_t i, j, n;
+
+    n = mpi_size( X );
+
+    if( buflen < n )
+        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+    memset( buf, 0, buflen );
+
+    for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+        buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+    return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, size_t count )
+{
+    int ret;
+    size_t i, v0, t1;
+    t_uint r0 = 0, r1;
+
+    v0 = count / (biL    );
+    t1 = count & (biL - 1);
+
+    i = mpi_msb( X ) + count;
+
+    if( X->n * biL < i )
+        MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+    ret = 0;
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = X->n; i > v0; i-- )
+            X->p[i - 1] = X->p[i - v0 - 1];
+
+        for( ; i > 0; i-- )
+            X->p[i - 1] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( t1 > 0 )
+    {
+        for( i = v0; i < X->n; i++ )
+        {
+            r1 = X->p[i] >> (biL - t1);
+            X->p[i] <<= t1;
+            X->p[i] |= r0;
+            r0 = r1;
+        }
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, size_t count )
+{
+    size_t i, v0, v1;
+    t_uint r0 = 0, r1;
+
+    v0 = count /  biL;
+    v1 = count & (biL - 1);
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = 0; i < X->n - v0; i++ )
+            X->p[i] = X->p[i + v0];
+
+        for( ; i < X->n; i++ )
+            X->p[i] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( v1 > 0 )
+    {
+        for( i = X->n; i > 0; i-- )
+        {
+            r1 = X->p[i - 1] << (biL - v1);
+            X->p[i - 1] >>= v1;
+            X->p[i - 1] |= r0;
+            r0 = r1;
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y )
+{
+    size_t i, j;
+
+    for( i = X->n; i > 0; i-- )
+        if( X->p[i - 1] != 0 )
+            break;
+
+    for( j = Y->n; j > 0; j-- )
+        if( Y->p[j - 1] != 0 )
+            break;
+
+    if( i == 0 && j == 0 )
+        return( 0 );
+
+    if( i > j ) return(  1 );
+    if( j > i ) return( -1 );
+
+    for( ; i > 0; i-- )
+    {
+        if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
+        if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y )
+{
+    size_t i, j;
+
+    for( i = X->n; i > 0; i-- )
+        if( X->p[i - 1] != 0 )
+            break;
+
+    for( j = Y->n; j > 0; j-- )
+        if( Y->p[j - 1] != 0 )
+            break;
+
+    if( i == 0 && j == 0 )
+        return( 0 );
+
+    if( i > j ) return(  X->s );
+    if( j > i ) return( -X->s );
+
+    if( X->s > 0 && Y->s < 0 ) return(  1 );
+    if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+    for( ; i > 0; i-- )
+    {
+        if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
+        if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( const mpi *X, t_sint z )
+{
+    mpi Y;
+    t_uint p[1];
+
+    *p  = ( z < 0 ) ? -z : z;
+    Y.s = ( z < 0 ) ? -1 : 1;
+    Y.n = 1;
+    Y.p = p;
+
+    return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B|  (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t i, j;
+    t_uint *o, *p, c;
+
+    if( X == B )
+    {
+        const mpi *T = A; A = X; B = T;
+    }
+
+    if( X != A )
+        MPI_CHK( mpi_copy( X, A ) );
+   
+    /*
+     * X should always be positive as a result of unsigned additions.
+     */
+    X->s = 1;
+
+    for( j = B->n; j > 0; j-- )
+        if( B->p[j - 1] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, j ) );
+
+    o = B->p; p = X->p; c = 0;
+
+    for( i = 0; i < j; i++, o++, p++ )
+    {
+        *p +=  c; c  = ( *p <  c );
+        *p += *o; c += ( *p < *o );
+    }
+
+    while( c != 0 )
+    {
+        if( i >= X->n )
+        {
+            MPI_CHK( mpi_grow( X, i + 1 ) );
+            p = X->p + i;
+        }
+
+        *p += c; c = ( *p < c ); i++;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Helper for mpi substraction
+ */
+static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
+{
+    size_t i;
+    t_uint c, z;
+
+    for( i = c = 0; i < n; i++, s++, d++ )
+    {
+        z = ( *d <  c );     *d -=  c;
+        c = ( *d < *s ) + z; *d -= *s;
+    }
+
+    while( c != 0 )
+    {
+        z = ( *d < c ); *d -= c;
+        c = z; i++; d++;
+    }
+}
+
+/*
+ * Unsigned substraction: X = |A| - |B|  (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
+{
+    mpi TB;
+    int ret;
+    size_t n;
+
+    if( mpi_cmp_abs( A, B ) < 0 )
+        return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+    mpi_init( &TB );
+
+    if( X == B )
+    {
+        MPI_CHK( mpi_copy( &TB, B ) );
+        B = &TB;
+    }
+
+    if( X != A )
+        MPI_CHK( mpi_copy( X, A ) );
+
+    /*
+     * X should always be positive as a result of unsigned substractions.
+     */
+    X->s = 1;
+
+    ret = 0;
+
+    for( n = B->n; n > 0; n-- )
+        if( B->p[n - 1] != 0 )
+            break;
+
+    mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+    mpi_free( &TB );
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s < 0 )
+    {
+        if( mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed substraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s > 0 )
+    {
+        if( mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed substraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */ 
+static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
+{
+    t_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_HUIT
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#else
+    for( ; i >= 16; i -= 16 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#endif
+
+    t++;
+
+    do {
+        *d += c; c = ( *d < c ); d++;
+    }
+    while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B  (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t i, j;
+    mpi TA, TB;
+
+    mpi_init( &TA ); mpi_init( &TB );
+
+    if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
+    if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
+
+    for( i = A->n; i > 0; i-- )
+        if( A->p[i - 1] != 0 )
+            break;
+
+    for( j = B->n; j > 0; j-- )
+        if( B->p[j - 1] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, i + j ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    for( i++; j > 0; j-- )
+        mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
+
+    X->s = A->s * B->s;
+
+cleanup:
+
+    mpi_free( &TB ); mpi_free( &TA );
+
+    return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    _B.s = 1;
+    _B.n = 1;
+    _B.p = p;
+    p[0] = b;
+
+    return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R  (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t i, n, t, k;
+    mpi X, Y, Z, T1, T2;
+
+    if( mpi_cmp_int( B, 0 ) == 0 )
+        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+    mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
+    mpi_init( &T1 ); mpi_init( &T2 );
+
+    if( mpi_cmp_abs( A, B ) < 0 )
+    {
+        if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
+        if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
+        return( 0 );
+    }
+
+    MPI_CHK( mpi_copy( &X, A ) );
+    MPI_CHK( mpi_copy( &Y, B ) );
+    X.s = Y.s = 1;
+
+    MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+    MPI_CHK( mpi_lset( &Z,  0 ) );
+    MPI_CHK( mpi_grow( &T1, 2 ) );
+    MPI_CHK( mpi_grow( &T2, 3 ) );
+
+    k = mpi_msb( &Y ) % biL;
+    if( k < biL - 1 )
+    {
+        k = biL - 1 - k;
+        MPI_CHK( mpi_shift_l( &X, k ) );
+        MPI_CHK( mpi_shift_l( &Y, k ) );
+    }
+    else k = 0;
+
+    n = X.n - 1;
+    t = Y.n - 1;
+    mpi_shift_l( &Y, biL * (n - t) );
+
+    while( mpi_cmp_mpi( &X, &Y ) >= 0 )
+    {
+        Z.p[n - t]++;
+        mpi_sub_mpi( &X, &X, &Y );
+    }
+    mpi_shift_r( &Y, biL * (n - t) );
+
+    for( i = n; i > t ; i-- )
+    {
+        if( X.p[i] >= Y.p[t] )
+            Z.p[i - t - 1] = ~0;
+        else
+        {
+#if defined(POLARSSL_HAVE_LONGLONG)
+            t_dbl r;
+
+            r  = (t_dbl) X.p[i] << biL;
+            r |= (t_dbl) X.p[i - 1];
+            r /= Y.p[t];
+            if( r > ((t_dbl) 1 << biL) - 1)
+                r = ((t_dbl) 1 << biL) - 1;
+
+            Z.p[i - t - 1] = (t_uint) r;
+#else
+            /*
+             * __udiv_qrnnd_c, from gmp/longlong.h
+             */
+            t_uint q0, q1, r0, r1;
+            t_uint d0, d1, d, m;
+
+            d  = Y.p[t];
+            d0 = ( d << biH ) >> biH;
+            d1 = ( d >> biH );
+
+            q1 = X.p[i] / d1;
+            r1 = X.p[i] - d1 * q1;
+            r1 <<= biH;
+            r1 |= ( X.p[i - 1] >> biH );
+
+            m = q1 * d0;
+            if( r1 < m )
+            {
+                q1--, r1 += d;
+                while( r1 >= d && r1 < m )
+                    q1--, r1 += d;
+            }
+            r1 -= m;
+
+            q0 = r1 / d1;
+            r0 = r1 - d1 * q0;
+            r0 <<= biH;
+            r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+            m = q0 * d0;
+            if( r0 < m )
+            {
+                q0--, r0 += d;
+                while( r0 >= d && r0 < m )
+                    q0--, r0 += d;
+            }
+            r0 -= m;
+
+            Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+        }
+
+        Z.p[i - t - 1]++;
+        do
+        {
+            Z.p[i - t - 1]--;
+
+            MPI_CHK( mpi_lset( &T1, 0 ) );
+            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+            T1.p[1] = Y.p[t];
+            MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+            MPI_CHK( mpi_lset( &T2, 0 ) );
+            T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+            T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+            T2.p[2] = X.p[i];
+        }
+        while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+        MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+        MPI_CHK( mpi_shift_l( &T1,  biL * (i - t - 1) ) );
+        MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+        if( mpi_cmp_int( &X, 0 ) < 0 )
+        {
+            MPI_CHK( mpi_copy( &T1, &Y ) );
+            MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+            MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+            Z.p[i - t - 1]--;
+        }
+    }
+
+    if( Q != NULL )
+    {
+        mpi_copy( Q, &Z );
+        Q->s = A->s * B->s;
+    }
+
+    if( R != NULL )
+    {
+        mpi_shift_r( &X, k );
+        mpi_copy( R, &X );
+
+        R->s = A->s;
+        if( mpi_cmp_int( R, 0 ) == 0 )
+            R->s = 1;
+    }
+
+cleanup:
+
+    mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
+    mpi_free( &T1 ); mpi_free( &T2 );
+
+    return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ *
+ * Returns 0 if successful
+ *         1 if memory allocation failed
+ *         POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
+{
+    mpi _B;
+    t_uint p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
+{
+    int ret;
+
+    if( mpi_cmp_int( B, 0 ) < 0 )
+        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+    MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+    while( mpi_cmp_int( R, 0 ) < 0 )
+      MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+    while( mpi_cmp_mpi( R, B ) >= 0 )
+      MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
+{
+    size_t i;
+    t_uint x, y, z;
+
+    if( b == 0 )
+        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+    if( b < 0 )
+        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+    /*
+     * handle trivial cases
+     */
+    if( b == 1 )
+    {
+        *r = 0;
+        return( 0 );
+    }
+
+    if( b == 2 )
+    {
+        *r = A->p[0] & 1;
+        return( 0 );
+    }
+
+    /*
+     * general case
+     */
+    for( i = A->n, y = 0; i > 0; i-- )
+    {
+        x  = A->p[i - 1];
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+
+        x <<= biH;
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+    }
+
+    /*
+     * If A is negative, then the current y represents a negative value.
+     * Flipping it to the positive side.
+     */
+    if( A->s < 0 && y != 0 )
+        y = b - y;
+
+    *r = y;
+
+    return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_uint *mm, const mpi *N )
+{
+    t_uint x, m0 = N->p[0];
+
+    x  = m0;
+    x += ( ( m0 + 2 ) & 4 ) << 1;
+    x *= ( 2 - ( m0 * x ) );
+
+    if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
+    if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
+    if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
+
+    *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
+{
+    size_t i, n, m;
+    t_uint u0, u1, *d;
+
+    memset( T->p, 0, T->n * ciL );
+
+    d = T->p;
+    n = N->n;
+    m = ( B->n < n ) ? B->n : n;
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * T = (T + u0*B + u1*N) / 2^biL
+         */
+        u0 = A->p[i];
+        u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+        mpi_mul_hlp( m, B->p, d, u0 );
+        mpi_mul_hlp( n, N->p, d, u1 );
+
+        *d++ = u0; d[n + 1] = 0;
+    }
+
+    memcpy( A->p, d, (n + 1) * ciL );
+
+    if( mpi_cmp_abs( A, N ) >= 0 )
+        mpi_sub_hlp( n, N->p, A->p );
+    else
+        /* prevent timing attacks */
+        mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
+{
+    t_uint z = 1;
+    mpi U;
+
+    U.n = U.s = z;
+    U.p = &z;
+
+    mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
+{
+    int ret;
+    size_t wbits, wsize, one = 1;
+    size_t i, j, nblimbs;
+    size_t bufsize, nbits;
+    t_uint ei, mm, state;
+    mpi RR, T, W[64];
+
+    if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    /*
+     * Init temps and window size
+     */
+    mpi_montg_init( &mm, N );
+    mpi_init( &RR ); mpi_init( &T );
+    memset( W, 0, sizeof( W ) );
+
+    i = mpi_msb( E );
+
+    wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+            ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
+
+    j = N->n + 1;
+    MPI_CHK( mpi_grow( X, j ) );
+    MPI_CHK( mpi_grow( &W[1],  j ) );
+    MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+    /*
+     * If 1st call, pre-compute R^2 mod N
+     */
+    if( _RR == NULL || _RR->p == NULL )
+    {
+        MPI_CHK( mpi_lset( &RR, 1 ) );
+        MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+        MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+        if( _RR != NULL )
+            memcpy( _RR, &RR, sizeof( mpi ) );
+    }
+    else
+        memcpy( &RR, _RR, sizeof( mpi ) );
+
+    /*
+     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+     */
+    if( mpi_cmp_mpi( A, N ) >= 0 )
+        mpi_mod_mpi( &W[1], A, N );
+    else   mpi_copy( &W[1], A );
+
+    mpi_montmul( &W[1], &RR, N, mm, &T );
+
+    /*
+     * X = R^2 * R^-1 mod N = R mod N
+     */
+    MPI_CHK( mpi_copy( X, &RR ) );
+    mpi_montred( X, N, mm, &T );
+
+    if( wsize > 1 )
+    {
+        /*
+         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+         */
+        j =  one << (wsize - 1);
+
+        MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+        MPI_CHK( mpi_copy( &W[j], &W[1]    ) );
+
+        for( i = 0; i < wsize - 1; i++ )
+            mpi_montmul( &W[j], &W[j], N, mm, &T );
+    
+        /*
+         * W[i] = W[i - 1] * W[1]
+         */
+        for( i = j + 1; i < (one << wsize); i++ )
+        {
+            MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+            MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+            mpi_montmul( &W[i], &W[1], N, mm, &T );
+        }
+    }
+
+    nblimbs = E->n;
+    bufsize = 0;
+    nbits   = 0;
+    wbits   = 0;
+    state   = 0;
+
+    while( 1 )
+    {
+        if( bufsize == 0 )
+        {
+            if( nblimbs-- == 0 )
+                break;
+
+            bufsize = sizeof( t_uint ) << 3;
+        }
+
+        bufsize--;
+
+        ei = (E->p[nblimbs] >> bufsize) & 1;
+
+        /*
+         * skip leading 0s
+         */
+        if( ei == 0 && state == 0 )
+            continue;
+
+        if( ei == 0 && state == 1 )
+        {
+            /*
+             * out of window, square X
+             */
+            mpi_montmul( X, X, N, mm, &T );
+            continue;
+        }
+
+        /*
+         * add ei to current window
+         */
+        state = 2;
+
+        nbits++;
+        wbits |= (ei << (wsize - nbits));
+
+        if( nbits == wsize )
+        {
+            /*
+             * X = X^wsize R^-1 mod N
+             */
+            for( i = 0; i < wsize; i++ )
+                mpi_montmul( X, X, N, mm, &T );
+
+            /*
+             * X = X * W[wbits] R^-1 mod N
+             */
+            mpi_montmul( X, &W[wbits], N, mm, &T );
+
+            state--;
+            nbits = 0;
+            wbits = 0;
+        }
+    }
+
+    /*
+     * process the remaining bits
+     */
+    for( i = 0; i < nbits; i++ )
+    {
+        mpi_montmul( X, X, N, mm, &T );
+
+        wbits <<= 1;
+
+        if( (wbits & (one << wsize)) != 0 )
+            mpi_montmul( X, &W[1], N, mm, &T );
+    }
+
+    /*
+     * X = A^E * R * R^-1 mod N = A^E mod N
+     */
+    mpi_montred( X, N, mm, &T );
+
+cleanup:
+
+    for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
+        mpi_free( &W[i] );
+
+    mpi_free( &W[1] ); mpi_free( &T );
+
+    if( _RR == NULL )
+        mpi_free( &RR );
+
+    return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
+{
+    int ret;
+    size_t lz, lzt;
+    mpi TG, TA, TB;
+
+    mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
+
+    MPI_CHK( mpi_copy( &TA, A ) );
+    MPI_CHK( mpi_copy( &TB, B ) );
+
+    lz = mpi_lsb( &TA );
+    lzt = mpi_lsb( &TB );
+
+    if ( lzt < lz )
+        lz = lzt;
+
+    MPI_CHK( mpi_shift_r( &TA, lz ) );
+    MPI_CHK( mpi_shift_r( &TB, lz ) );
+
+    TA.s = TB.s = 1;
+
+    while( mpi_cmp_int( &TA, 0 ) != 0 )
+    {
+        MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
+        MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
+
+        if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
+            MPI_CHK( mpi_shift_r( &TA, 1 ) );
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
+            MPI_CHK( mpi_shift_r( &TB, 1 ) );
+        }
+    }
+
+    MPI_CHK( mpi_shift_l( &TB, lz ) );
+    MPI_CHK( mpi_copy( G, &TB ) );
+
+cleanup:
+
+    mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
+
+    return( ret );
+}
+
+int mpi_fill_random( mpi *X, size_t size, int (*f_rng)(void *), void *p_rng )
+{
+    int ret;
+    size_t k;
+    unsigned char *p;
+
+    MPI_CHK( mpi_grow( X, size ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    p = (unsigned char *) X->p;
+    for( k = 0; k < X->n * ciL; k++ )
+        *p++ = (unsigned char) f_rng( p_rng );
+
+cleanup:
+    return( ret );
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
+{
+    int ret;
+    mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+    if( mpi_cmp_int( N, 0 ) <= 0 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
+    mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
+    mpi_init( &V1 ); mpi_init( &V2 );
+
+    MPI_CHK( mpi_gcd( &G, A, N ) );
+
+    if( mpi_cmp_int( &G, 1 ) != 0 )
+    {
+        ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+        goto cleanup;
+    }
+
+    MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
+    MPI_CHK( mpi_copy( &TU, &TA ) );
+    MPI_CHK( mpi_copy( &TB, N ) );
+    MPI_CHK( mpi_copy( &TV, N ) );
+
+    MPI_CHK( mpi_lset( &U1, 1 ) );
+    MPI_CHK( mpi_lset( &U2, 0 ) );
+    MPI_CHK( mpi_lset( &V1, 0 ) );
+    MPI_CHK( mpi_lset( &V2, 1 ) );
+
+    do
+    {
+        while( ( TU.p[0] & 1 ) == 0 )
+        {
+            MPI_CHK( mpi_shift_r( &TU, 1 ) );
+
+            if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+            {
+                MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
+                MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
+            }
+
+            MPI_CHK( mpi_shift_r( &U1, 1 ) );
+            MPI_CHK( mpi_shift_r( &U2, 1 ) );
+        }
+
+        while( ( TV.p[0] & 1 ) == 0 )
+        {
+            MPI_CHK( mpi_shift_r( &TV, 1 ) );
+
+            if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+            {
+                MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
+                MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
+            }
+
+            MPI_CHK( mpi_shift_r( &V1, 1 ) );
+            MPI_CHK( mpi_shift_r( &V2, 1 ) );
+        }
+
+        if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
+            MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
+            MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
+            MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
+            MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
+        }
+    }
+    while( mpi_cmp_int( &TU, 0 ) != 0 );
+
+    while( mpi_cmp_int( &V1, 0 ) < 0 )
+        MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
+
+    while( mpi_cmp_mpi( &V1, N ) >= 0 )
+        MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
+
+    MPI_CHK( mpi_copy( X, &V1 ) );
+
+cleanup:
+
+    mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
+    mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
+    mpi_free( &V1 ); mpi_free( &V2 );
+
+    return( ret );
+}
+
+static const int small_prime[] =
+{
+        3,    5,    7,   11,   13,   17,   19,   23,
+       29,   31,   37,   41,   43,   47,   53,   59,
+       61,   67,   71,   73,   79,   83,   89,   97,
+      101,  103,  107,  109,  113,  127,  131,  137,
+      139,  149,  151,  157,  163,  167,  173,  179,
+      181,  191,  193,  197,  199,  211,  223,  227,
+      229,  233,  239,  241,  251,  257,  263,  269,
+      271,  277,  281,  283,  293,  307,  311,  313,
+      317,  331,  337,  347,  349,  353,  359,  367,
+      373,  379,  383,  389,  397,  401,  409,  419,
+      421,  431,  433,  439,  443,  449,  457,  461,
+      463,  467,  479,  487,  491,  499,  503,  509,
+      521,  523,  541,  547,  557,  563,  569,  571,
+      577,  587,  593,  599,  601,  607,  613,  617,
+      619,  631,  641,  643,  647,  653,  659,  661,
+      673,  677,  683,  691,  701,  709,  719,  727,
+      733,  739,  743,  751,  757,  761,  769,  773,
+      787,  797,  809,  811,  821,  823,  827,  829,
+      839,  853,  857,  859,  863,  877,  881,  883,
+      887,  907,  911,  919,  929,  937,  941,  947,
+      953,  967,  971,  977,  983,  991,  997, -103
+};
+
+/*
+ * Miller-Rabin primality test  (HAC 4.24)
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
+{
+    int ret, xs;
+    size_t i, j, n, s;
+    mpi W, R, T, A, RR;
+
+    if( mpi_cmp_int( X, 0 ) == 0 ||
+        mpi_cmp_int( X, 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+    if( mpi_cmp_int( X, 2 ) == 0 )
+        return( 0 );
+
+    mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
+    mpi_init( &RR );
+
+    xs = X->s; X->s = 1;
+
+    /*
+     * test trivial factors first
+     */
+    if( ( X->p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+    for( i = 0; small_prime[i] > 0; i++ )
+    {
+        t_uint r;
+
+        if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
+            return( 0 );
+
+        MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
+
+        if( r == 0 )
+            return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+    }
+
+    /*
+     * W = |X| - 1
+     * R = W >> lsb( W )
+     */
+    MPI_CHK( mpi_sub_int( &W, X, 1 ) );
+    s = mpi_lsb( &W );
+    MPI_CHK( mpi_copy( &R, &W ) );
+    MPI_CHK( mpi_shift_r( &R, s ) );
+
+    i = mpi_msb( X );
+    /*
+     * HAC, table 4.4
+     */
+    n = ( ( i >= 1300 ) ?  2 : ( i >=  850 ) ?  3 :
+          ( i >=  650 ) ?  4 : ( i >=  350 ) ?  8 :
+          ( i >=  250 ) ? 12 : ( i >=  150 ) ? 18 : 27 );
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * pick a random A, 1 < A < |X| - 1
+         */
+        mpi_fill_random( &A, X->n, f_rng, p_rng );
+
+        if( mpi_cmp_mpi( &A, &W ) >= 0 )
+        {
+            j = mpi_msb( &A ) - mpi_msb( &W );
+            MPI_CHK( mpi_shift_r( &A, j + 1 ) );
+        }
+        A.p[0] |= 3;
+
+        /*
+         * A = A^R mod |X|
+         */
+        MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+        if( mpi_cmp_mpi( &A, &W ) == 0 ||
+            mpi_cmp_int( &A,  1 ) == 0 )
+            continue;
+
+        j = 1;
+        while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
+        {
+            /*
+             * A = A * A mod |X|
+             */
+            MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
+            MPI_CHK( mpi_mod_mpi( &A, &T, X  ) );
+
+            if( mpi_cmp_int( &A, 1 ) == 0 )
+                break;
+
+            j++;
+        }
+
+        /*
+         * not prime if A != |X| - 1 or A == 1
+         */
+        if( mpi_cmp_mpi( &A, &W ) != 0 ||
+            mpi_cmp_int( &A,  1 ) == 0 )
+        {
+            ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+            break;
+        }
+    }
+
+cleanup:
+
+    X->s = xs;
+
+    mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
+    mpi_free( &RR );
+
+    return( ret );
+}
+
+/*
+ * Prime number generation
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+                   int (*f_rng)(void *), void *p_rng )
+{
+    int ret;
+    size_t k, n;
+    mpi Y;
+
+    if( nbits < 3 || nbits > 4096 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &Y );
+
+    n = BITS_TO_LIMBS( nbits );
+
+    mpi_fill_random( X, n, f_rng, p_rng );
+
+    k = mpi_msb( X );
+    if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
+    if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
+
+    X->p[0] |= 3;
+
+    if( dh_flag == 0 )
+    {
+        while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+        {
+            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                goto cleanup;
+
+            MPI_CHK( mpi_add_int( X, X, 2 ) );
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
+        MPI_CHK( mpi_shift_r( &Y, 1 ) );
+
+        while( 1 )
+        {
+            if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
+            {
+                if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
+                    break;
+
+                if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                    goto cleanup;
+            }
+
+            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                goto cleanup;
+
+            MPI_CHK( mpi_add_int( &Y, X, 1 ) );
+            MPI_CHK( mpi_add_int(  X, X, 2 ) );
+            MPI_CHK( mpi_shift_r( &Y, 1 ) );
+        }
+    }
+
+cleanup:
+
+    mpi_free( &Y );
+
+    return( ret );
+}
+
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+
+#define GCD_PAIR_COUNT  3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+    { 693, 609, 21 },
+    { 1764, 868, 28 },
+    { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mpi_self_test( int verbose )
+{
+    int ret, i;
+    mpi A, E, N, X, Y, U, V;
+
+    mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
+    mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
+
+    MPI_CHK( mpi_read_string( &A, 16,
+        "EFE021C2645FD1DC586E69184AF4A31E" \
+        "D5F53E93B5F123FA41680867BA110131" \
+        "944FE7952E2517337780CB0DB80E61AA" \
+        "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+    MPI_CHK( mpi_read_string( &E, 16,
+        "B2E7EFD37075B9F03FF989C7C5051C20" \
+        "34D2A323810251127E7BF8625A4F49A5" \
+        "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+        "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+    MPI_CHK( mpi_read_string( &N, 16,
+        "0066A198186C18C10B2F5ED9B522752A" \
+        "9830B69916E535C8F047518A889A43A5" \
+        "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+    MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "602AB7ECA597A3D6B56FF9829A5E8B85" \
+        "9E857EA95A03512E2BAE7391688D264A" \
+        "A5663B0341DB9CCFD2C4C5F421FEC814" \
+        "8001B72E848A38CAE1C65F78E56ABDEF" \
+        "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+        "ECF677152EF804370C1A305CAF3B5BF1" \
+        "30879B56C61DE584A0F53A2447A51E" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #1 (mul_mpi): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+    MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "256567336059E52CAE22925474705F39A94" ) );
+
+    MPI_CHK( mpi_read_string( &V, 16,
+        "6613F26162223DF488E9CD48CC132C7A" \
+        "0AC93C701B001B092E4E5B9F73BCD27B" \
+        "9EE50D0657C77F374E903CDFA4C642" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #2 (div_mpi): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 ||
+        mpi_cmp_mpi( &Y, &V ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+    MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "36E139AEA55215609D2816998ED020BB" \
+        "BD96C37890F65171D948E9BC7CBAA4D9" \
+        "325D24D6A3C12710F10A09FA08AB87" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #3 (exp_mod): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+#if defined(POLARSSL_GENPRIME)
+    MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+        "C3DBA76456363A10869622EAC2DD84EC" \
+        "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #4 (inv_mod): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+#endif
+
+    if( verbose != 0 )
+        printf( "  MPI test #5 (simple gcd): " );
+
+    for ( i = 0; i < GCD_PAIR_COUNT; i++)
+    {
+        MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
+        MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+	    MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+
+	    if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+	    {
+		    if( verbose != 0 )
+			    printf( "failed at %d\n", i );
+
+		    return( 1 );
+	    }
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+cleanup:
+
+    if( ret != 0 && verbose != 0 )
+        printf( "Unexpected error, return code = %08X\n", ret );
+
+    mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
+    mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( ret );
+}
+
+#endif
+
+#endif

+ 1040 - 0
thirdparty/PolarSSL/library/camellia.c

@@ -0,0 +1,1040 @@
+/*
+ *  Camellia implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The Camellia block cipher was designed by NTT and Mitsubishi Electric
+ *  Corporation.
+ *
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+#include "polarssl/camellia.h"
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
+        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 3]       );       \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+static const unsigned char SIGMA_CHARS[6][8] =
+{
+    { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
+    { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },
+    { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },
+    { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },
+    { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },
+    { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }
+};
+
+#ifdef POLARSSL_CAMELLIA_SMALL_MEMORY
+
+static const unsigned char FSb[256] =
+{
+    112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
+     35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
+    134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
+    166,225, 57,202,213, 71, 93, 61,217,  1, 90,214, 81, 86,108, 77,
+    139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
+    223, 76,203,194, 52,126,118,  5,109,183,169, 49,209, 23,  4,215,
+     20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
+    254, 68,207,178,195,181,122,145, 36,  8,232,168, 96,252,105, 80,
+    170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
+     16,196,  0, 72,163,247,117,219,138,  3,230,218,  9, 63,221,148,
+    135, 92,131,  2,205, 74,144, 51,115,103,246,243,157,127,191,226,
+     82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
+    233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
+    120,152,  6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
+    114,  7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
+     64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
+#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
+#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
+
+#else
+
+static const unsigned char FSb[256] =
+{
+    112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
+    35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
+    134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
+    166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
+    139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
+    223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
+    20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
+    254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
+    170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
+    16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
+    135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
+    82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
+    233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
+    120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
+    114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
+    64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158
+};
+
+static const unsigned char FSb2[256] =
+{
+    224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,
+    70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,
+    13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,
+    77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,
+    23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,
+    191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,
+    40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,
+    253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,
+    85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,
+    32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,
+    15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,
+    164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,
+    211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,
+    240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,
+    228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,
+    128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61
+};
+
+static const unsigned char FSb3[256] =
+{
+    56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,
+    145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,
+    67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,
+    83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,
+    197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,
+    239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,
+    10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,
+    127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,
+    85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,
+    8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,
+    195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
+    41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,
+    244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,
+    60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,
+    57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,
+    32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79
+};
+
+static const unsigned char FSb4[256] =
+{
+    112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,
+    134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,
+    139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,
+    20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,
+    170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,
+    135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,
+    233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,
+    114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,
+    130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,
+    184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,
+    13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,
+    88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,
+    208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,
+    92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,
+    121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,
+    7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) FSb2[(n)]
+#define SBOX3(n) FSb3[(n)]
+#define SBOX4(n) FSb4[(n)]
+
+#endif
+
+static const unsigned char shifts[2][4][4] =
+{
+    {
+        { 1, 1, 1, 1 }, /* KL */
+        { 0, 0, 0, 0 }, /* KR */
+        { 1, 1, 1, 1 }, /* KA */
+        { 0, 0, 0, 0 }  /* KB */
+    },
+    {
+        { 1, 0, 1, 1 }, /* KL */
+        { 1, 1, 0, 1 }, /* KR */
+        { 1, 1, 1, 0 }, /* KA */
+        { 1, 1, 0, 1 }  /* KB */
+    }
+};
+
+static const signed char indexes[2][4][20] =
+{
+    {
+        {  0,  1,  2,  3,  8,  9, 10, 11, 38, 39,
+          36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
+        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
+        {  4,  5,  6,  7, 12, 13, 14, 15, 16, 17,
+          18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
+        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+          -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }  /* KB -> RK */
+    },
+    {
+        {  0,  1,  2,  3, 61, 62, 63, 60, -1, -1,
+          -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
+        { -1, -1, -1, -1,  8,  9, 10, 11, 16, 17,
+          18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
+        { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
+          56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
+        {  4,  5,  6,  7, 65, 66, 67, 64, 20, 21,
+          22, 23, -1, -1, -1, -1, 43, 40, 41, 42 }  /* KB -> RK */
+    }
+};
+
+static const signed char transposes[2][20] =
+{
+    {
+        21, 22, 23, 20,
+        -1, -1, -1, -1,
+        18, 19, 16, 17,
+        11,  8,  9, 10,
+        15, 12, 13, 14
+    },
+    {
+        25, 26, 27, 24,
+        29, 30, 31, 28,
+        18, 19, 16, 17,
+        -1, -1, -1, -1,
+        -1, -1, -1, -1
+    }
+};
+
+/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
+#define ROTL(DEST, SRC, SHIFT)                                      \
+{                                                                   \
+    (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT));   \
+    (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT));   \
+    (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT));   \
+    (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT));   \
+}
+
+#define FL(XL, XR, KL, KR)                                          \
+{                                                                   \
+    (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR);   \
+    (XL) = ((XR) | (KR)) ^ (XL);                                    \
+}
+    
+#define FLInv(YL, YR, KL, KR)                                       \
+{                                                                   \
+    (YL) = ((YR) | (KR)) ^ (YL);                                    \
+    (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR);   \
+}
+    
+#define SHIFT_AND_PLACE(INDEX, OFFSET)                      \
+{                                                           \
+    TK[0] = KC[(OFFSET) * 4 + 0];                           \
+    TK[1] = KC[(OFFSET) * 4 + 1];                           \
+    TK[2] = KC[(OFFSET) * 4 + 2];                           \
+    TK[3] = KC[(OFFSET) * 4 + 3];                           \
+                                                            \
+    for ( i = 1; i <= 4; i++ )                              \
+        if (shifts[(INDEX)][(OFFSET)][i -1])                \
+            ROTL(TK + i * 4, TK, (15 * i) % 32);            \
+                                                            \
+    for ( i = 0; i < 20; i++ )                              \
+        if (indexes[(INDEX)][(OFFSET)][i] != -1) {          \
+        RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ];        \
+    }                                                       \
+}
+
+static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2])
+{
+    uint32_t I0, I1;
+    I0 = x[0] ^ k[0];
+    I1 = x[1] ^ k[1];
+
+    I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) |
+         (SBOX2((I0 >> 16) & 0xFF) << 16) |
+         (SBOX3((I0 >>  8) & 0xFF) <<  8) |
+         (SBOX4((I0      ) & 0xFF)      );
+    I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) |
+         (SBOX3((I1 >> 16) & 0xFF) << 16) |
+         (SBOX4((I1 >>  8) & 0xFF) <<  8) |
+         (SBOX1((I1      ) & 0xFF)      );
+
+    I0 ^= (I1 << 8) | (I1 >> 24);
+    I1 ^= (I0 << 16) | (I0 >> 16);
+    I0 ^= (I1 >> 8) | (I1 << 24);
+    I1 ^= (I0 >> 8) | (I0 << 24);
+
+    z[0] ^= I1;
+    z[1] ^= I0;
+}
+
+/*
+ * Camellia key schedule (encryption)
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+    int idx;
+    size_t i;
+    uint32_t *RK;
+    unsigned char t[64];
+    uint32_t SIGMA[6][2];
+    uint32_t KC[16];
+    uint32_t TK[20];
+
+    RK = ctx->rk;
+
+    memset(t, 0, 64);
+    memset(RK, 0, sizeof(ctx->rk));
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 3; idx = 0; break;
+        case 192:
+        case 256: ctx->nr = 4; idx = 1; break;
+        default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+    }
+
+    for( i = 0; i < keysize / 8; ++i)
+        t[i] = key[i];
+
+    if (keysize == 192) {
+        for (i = 0; i < 8; i++)
+            t[24 + i] = ~t[16 + i];
+    }
+
+    /*
+     * Prepare SIGMA values
+     */
+    for (i = 0; i < 6; i++) {
+        GET_ULONG_BE(SIGMA[i][0], SIGMA_CHARS[i], 0);
+        GET_ULONG_BE(SIGMA[i][1], SIGMA_CHARS[i], 4);
+    }
+
+    /*
+     * Key storage in KC
+     * Order: KL, KR, KA, KB
+     */
+    memset(KC, 0, sizeof(KC));
+
+    /* Store KL, KR */
+    for (i = 0; i < 8; i++)
+        GET_ULONG_BE(KC[i], t, i * 4);
+
+    /* Generate KA */
+    for( i = 0; i < 4; ++i)
+        KC[8 + i] = KC[i] ^ KC[4 + i];
+
+    camellia_feistel(KC + 8, SIGMA[0], KC + 10);
+    camellia_feistel(KC + 10, SIGMA[1], KC + 8);
+
+    for( i = 0; i < 4; ++i)
+        KC[8 + i] ^= KC[i];
+
+    camellia_feistel(KC + 8, SIGMA[2], KC + 10);
+    camellia_feistel(KC + 10, SIGMA[3], KC + 8);
+
+    if (keysize > 128) {
+        /* Generate KB */
+        for( i = 0; i < 4; ++i)
+            KC[12 + i] = KC[4 + i] ^ KC[8 + i];
+
+        camellia_feistel(KC + 12, SIGMA[4], KC + 14);
+        camellia_feistel(KC + 14, SIGMA[5], KC + 12);
+    }
+
+    /*
+     * Generating subkeys
+     */ 
+
+    /* Manipulating KL */
+    SHIFT_AND_PLACE(idx, 0);
+
+    /* Manipulating KR */
+    if (keysize > 128) {
+        SHIFT_AND_PLACE(idx, 1);
+    }
+
+    /* Manipulating KA */
+    SHIFT_AND_PLACE(idx, 2);
+
+    /* Manipulating KB */
+    if (keysize > 128) {
+        SHIFT_AND_PLACE(idx, 3);
+    }
+
+    /* Do transpositions */
+    for ( i = 0; i < 20; i++ ) {
+        if (transposes[idx][i] != -1) {
+            RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Camellia key schedule (decryption)
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+    int idx;
+    size_t i;
+    camellia_context cty;
+    uint32_t *RK;
+    uint32_t *SK;
+    int ret;
+
+    switch( keysize )
+    {
+        case 128: ctx->nr = 3; idx = 0; break;
+        case 192:
+        case 256: ctx->nr = 4; idx = 1; break;
+        default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+    }
+
+    RK = ctx->rk;
+
+    ret = camellia_setkey_enc(&cty, key, keysize);
+    if( ret != 0 )
+        return( ret );
+
+    SK = cty.rk + 24 * 2 + 8 * idx * 2;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4)
+    {
+        *RK++ = *SK++;
+        *RK++ = *SK++;
+    }
+
+    SK -= 2;
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+    memset( &cty, 0, sizeof( camellia_context ) );
+
+    return( 0 );
+}
+
+/*
+ * Camellia-ECB block encryption/decryption
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] )
+{
+    int NR;
+    uint32_t *RK, X[4];
+
+    ( (void) mode );
+
+    NR = ctx->nr;
+    RK = ctx->rk;
+
+    GET_ULONG_BE( X[0], input,  0 );
+    GET_ULONG_BE( X[1], input,  4 );
+    GET_ULONG_BE( X[2], input,  8 );
+    GET_ULONG_BE( X[3], input, 12 );
+
+    X[0] ^= *RK++;
+    X[1] ^= *RK++;
+    X[2] ^= *RK++;
+    X[3] ^= *RK++;
+
+    while (NR) {
+        --NR;
+        camellia_feistel(X, RK, X + 2);
+        RK += 2;
+        camellia_feistel(X + 2, RK, X);
+        RK += 2;
+        camellia_feistel(X, RK, X + 2);
+        RK += 2;
+        camellia_feistel(X + 2, RK, X);
+        RK += 2;
+        camellia_feistel(X, RK, X + 2);
+        RK += 2;
+        camellia_feistel(X + 2, RK, X);
+        RK += 2;
+
+        if (NR) {
+            FL(X[0], X[1], RK[0], RK[1]);
+            RK += 2;
+            FLInv(X[2], X[3], RK[0], RK[1]);
+            RK += 2;
+        }
+    }
+
+    X[2] ^= *RK++;
+    X[3] ^= *RK++;
+    X[0] ^= *RK++;
+    X[1] ^= *RK++;
+
+    PUT_ULONG_BE( X[2], output,  0 );
+    PUT_ULONG_BE( X[3], output,  4 );
+    PUT_ULONG_BE( X[0], output,  8 );
+    PUT_ULONG_BE( X[1], output, 12 );
+
+    return( 0 );
+}
+
+/*
+ * Camellia-CBC buffer encryption/decryption
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[16];
+
+    if( length % 16 )
+        return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
+
+    if( mode == CAMELLIA_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 16 );
+            camellia_crypt_ecb( ctx, mode, input, output );
+
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+    else
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            camellia_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * Camellia-CFB128 buffer encryption/decryption
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+                       int mode,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c;
+    size_t n = *iv_off;
+
+    if( mode == CAMELLIA_DECRYPT )
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+            c = *input++;
+            *output++ = (unsigned char)( c ^ iv[n] );
+            iv[n] = (unsigned char) c;
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+    else
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+            n = (n + 1) & 0x0F;
+        }
+    }
+
+    *iv_off = n;
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR buffer encryption/decryption
+ */
+int camellia_crypt_ctr( camellia_context *ctx,
+                       size_t length,
+                       size_t *nc_off,
+                       unsigned char nonce_counter[16],
+                       unsigned char stream_block[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int c, i, cb;
+    size_t n = *nc_off;
+
+    while( length-- )
+    {
+        if( n == 0 ) {
+            camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, stream_block );
+
+            i = 15;
+            do {
+               nonce_counter[i]++;
+               cb = nonce_counter[i] == 0;
+            } while( i-- && cb );
+
+        }
+        c = *input++;
+        *output++ = (unsigned char)( c ^ stream_block[n] );
+
+        n = (n + 1) & 0x0F;
+    }
+
+    *nc_off = n;
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+
+/*
+ * Camellia test vectors from:
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
+ *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
+ *   http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
+ *                      (For each bitlength: Key 0, Nr 39)
+ */
+#define CAMELLIA_TESTS_ECB  2
+
+static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
+{
+    {
+        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+    },
+    {
+        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+    },
+    {
+        { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+          0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+          0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+    },
+};
+
+static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
+{
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+    { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
+{
+    {
+        { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+          0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+        { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
+          0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
+    },
+    {
+        { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+          0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+        { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
+          0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
+    },
+    {
+        { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+          0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+        { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
+          0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
+    }
+};
+
+#define CAMELLIA_TESTS_CBC  3
+
+static const unsigned char camellia_test_cbc_key[3][32] =
+{
+        { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+          0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+    ,
+        { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+          0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+          0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
+    ,
+        { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+          0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+          0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+          0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char camellia_test_cbc_iv[16] =
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
+;
+
+static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
+{
+    { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+      0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
+    { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+      0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
+    { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+      0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
+
+};
+
+static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
+{
+    {
+        { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
+          0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
+        { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
+          0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
+        { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
+          0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
+    },
+    {
+        { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
+          0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
+        { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
+          0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
+        { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
+          0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
+    },
+    {
+        { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
+          0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
+        { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
+          0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
+        { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
+          0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
+    }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc5528.html
+ */
+
+static const unsigned char camellia_test_ctr_key[3][16] =
+{
+    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
+{
+    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char camellia_test_ctr_pt[3][48] =
+{
+    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+      0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char camellia_test_ctr_ct[3][48] =
+{
+    { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
+      0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
+    { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
+      0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
+      0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
+      0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
+    { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
+      0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
+      0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
+      0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
+      0xDF, 0x50, 0x86, 0x96 }
+};
+
+static const int camellia_test_ctr_len[3] =
+    { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int camellia_self_test( int verbose )
+{
+    int i, j, u, v;
+    unsigned char key[32];
+    unsigned char buf[64];
+    unsigned char src[16];
+    unsigned char dst[16];
+    unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    size_t offset, len;
+    unsigned char nonce_counter[16];
+    unsigned char stream_block[16];
+#endif
+
+    camellia_context ctx;
+
+    memset( key, 0, 32 );
+
+    for (j = 0; j < 6; j++) {
+        u = j >> 1;
+    v = j & 1;
+
+    if( verbose != 0 )
+        printf( "  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
+                (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
+
+    for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
+        memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
+
+        if (v == CAMELLIA_DECRYPT) {
+            camellia_setkey_dec(&ctx, key, 128 + u * 64);
+            memcpy(src, camellia_test_ecb_cipher[u][i], 16);
+            memcpy(dst, camellia_test_ecb_plain[i], 16);
+        } else { /* CAMELLIA_ENCRYPT */
+            camellia_setkey_enc(&ctx, key, 128 + u * 64);
+            memcpy(src, camellia_test_ecb_plain[i], 16);
+            memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
+        }
+
+        camellia_crypt_ecb(&ctx, v, src, buf);
+
+        if( memcmp( buf, dst, 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    /*
+     * CBC mode
+     */
+    for( j = 0; j < 6; j++ )
+    {
+        u = j >> 1;
+        v = j  & 1;
+
+        if( verbose != 0 )
+            printf( "  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
+                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+    memcpy( src, camellia_test_cbc_iv, 16);
+    memcpy( dst, camellia_test_cbc_iv, 16);
+    memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
+
+    if (v == CAMELLIA_DECRYPT) {
+        camellia_setkey_dec(&ctx, key, 128 + u * 64);
+    } else {
+        camellia_setkey_enc(&ctx, key, 128 + u * 64);
+    }
+
+    for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
+
+        if (v == CAMELLIA_DECRYPT) {
+            memcpy( iv , src, 16 );
+            memcpy(src, camellia_test_cbc_cipher[u][i], 16);
+            memcpy(dst, camellia_test_cbc_plain[i], 16);
+        } else { /* CAMELLIA_ENCRYPT */
+            memcpy( iv , dst, 16 );
+            memcpy(src, camellia_test_cbc_plain[i], 16);
+            memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
+        }
+
+        camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
+
+        if( memcmp( buf, dst, 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    /*
+     * CTR mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  CAMELLIA-CTR-128 (%s): ",
+                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
+        memcpy( key, camellia_test_ctr_key[u], 16 );
+
+        offset = 0;
+        camellia_setkey_enc( &ctx, key, 128 );
+
+        if( v == CAMELLIA_DECRYPT )
+        {
+            len = camellia_test_ctr_len[u];
+            memcpy( buf, camellia_test_ctr_ct[u], len );
+
+            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+            if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+        else
+        {
+            len = camellia_test_ctr_len[u];
+            memcpy( buf, camellia_test_ctr_pt[u], len );
+
+            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+            if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+    return ( 0 );
+}
+
+#endif
+
+#endif

+ 196 - 0
thirdparty/PolarSSL/library/certs.c

@@ -0,0 +1,196 @@
+/*
+ *  X.509 test certificates
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_CERTS_C)
+
+const char test_ca_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n"
+"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n"
+"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n"
+"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n"
+"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n"
+"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n"
+"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n"
+"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n"
+"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n"
+"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n"
+"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n"
+"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n"
+"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n"
+"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n"
+"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n"
+"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_ca_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"Proc-Type: 4,ENCRYPTED\r\n"
+"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n"
+"\r\n"
+"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n"
+"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n"
+"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n"
+"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n"
+"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n"
+"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n"
+"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n"
+"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n"
+"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n"
+"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n"
+"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n"
+"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n"
+"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n"
+"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n"
+"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n"
+"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n"
+"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n"
+"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n"
+"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n"
+"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n"
+"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n"
+"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n"
+"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n"
+"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n"
+"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_ca_pwd[] = "PolarSSLTest";
+
+const char test_srv_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n"
+"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n"
+"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n"
+"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n"
+"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n"
+"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n"
+"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
+"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n"
+"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n"
+"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n"
+"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n"
+"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n"
+"/WzRyYRBRjAI49mzHX6raleqnw==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_srv_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEogIBAAKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS0/FDUEeW\r\n"
+"Ellkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4KwVzlw7aPs\r\n"
+"FRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms+Vruf5Ke\r\n"
+"pgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6babFtpzAK6\r\n"
+"FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZnm5akmXi\r\n"
+"iD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABAoIBABaJ9eiRQq4Ypv+w\r\n"
+"UTcVpLC0oTueWzcpor1i1zjG4Vzqe/Ok2FqyGToGKMlFK7Hwwa+LEyeJ3xyV5yd4\r\n"
+"v1Mw9bDZFdJC1eCBjoUAHtX6k9HOE0Vd6woVQ4Vi6OPI1g7B5Mnr/58rNrnN6TMs\r\n"
+"x58NF6euecwTU811QJrZtLbX7j2Cr28yB2Vs8qyYlHwVw5jbDOv43D7vU5gmlIDN\r\n"
+"0JQRuWAnOuPzZNoJr4SfJKqHNGxYYY6pHZ1s0dOTLIDb/B8KQWapA2kRmZyid2EH\r\n"
+"nwzgLbAsHJCf+bQnhXjXuxtUsrcIL8noZLazlOMxwNEammglVWW23Ud/QRnFgJg5\r\n"
+"UgcAcRECgYEA19uYetht5qmwdJ+12oC6zeO+vXLcyD9gon23T5J6w2YThld7/OW0\r\n"
+"oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n"
+"GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n"
+"//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n"
+"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n"
+"LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n"
+"Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n"
+"ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n"
+"8EFrye7wmzpthrjOgZnUMQKBgE9Lhsz/5J0Nis6Y+2Pqn3CLKEukg9Ewtqdct2y0\r\n"
+"5Dcta0F3TyCRIxlCDKTL/BslqMtfAdY4H268UO0+8IAQMn9boqzBrHIgs/pvc5kx\r\n"
+"TbKHmw2wtWR6vYersBKVgVpbCGSRssDYHGFu1n74qM4HJ/RGcR1zI9QUe1gopSFD\r\n"
+"xDtLAoGAVAdWvrqDwgoL2hHW3scGpxdE/ygJDOwHnf+1B9goKAOP5lf2FJaiAxf3\r\n"
+"ectoPOgZbCmm/iiDmigu703ld3O+VoCLDD4qx3R+KyALL78gtVJYzSRiKhzgCZ3g\r\n"
+"mKsIVRBq4IfwiwyMNG2BYZQAwbSDjjPtn/kPBduPzPj7eriByhI=\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_cli_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"
+"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"
+"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"
+"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n"
+"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"
+"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"
+"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
+"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n"
+"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n"
+"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n"
+"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n"
+"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n"
+"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_cli_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"
+"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n"
+"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n"
+"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n"
+"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n"
+"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n"
+"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n"
+"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n"
+"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n"
+"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n"
+"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n"
+"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n"
+"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n"
+"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n"
+"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n"
+"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n"
+"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n"
+"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n"
+"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n"
+"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n"
+"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n"
+"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n"
+"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n"
+"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n"
+"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_dhm_params[] =
+"-----BEGIN DH PARAMETERS-----\r\n"
+"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
+"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
+"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
+"-----END DH PARAMETERS-----\r\n";
+
+#endif

+ 536 - 0
thirdparty/PolarSSL/library/cipher.c

@@ -0,0 +1,536 @@
+/**
+ * \file cipher.c
+ * 
+ * \brief Generic cipher wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher.h"
+#include "polarssl/cipher_wrap.h"
+
+#include <stdlib.h>
+#if defined ( __GNUC__ )
+#include <my_strings.h>
+#endif
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+static const int supported_ciphers[] = {
+
+#if defined(POLARSSL_AES_C)
+        POLARSSL_CIPHER_AES_128_CBC,
+        POLARSSL_CIPHER_AES_192_CBC,
+        POLARSSL_CIPHER_AES_256_CBC,
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+        POLARSSL_CIPHER_AES_128_CFB128,
+        POLARSSL_CIPHER_AES_192_CFB128,
+        POLARSSL_CIPHER_AES_256_CFB128,
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+        POLARSSL_CIPHER_AES_128_CTR,
+        POLARSSL_CIPHER_AES_192_CTR,
+        POLARSSL_CIPHER_AES_256_CTR,
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif /* defined(POLARSSL_AES_C) */
+
+#if defined(POLARSSL_CAMELLIA_C)
+        POLARSSL_CIPHER_CAMELLIA_128_CBC,
+        POLARSSL_CIPHER_CAMELLIA_192_CBC,
+        POLARSSL_CIPHER_CAMELLIA_256_CBC,
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+        POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+        POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+        POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+        POLARSSL_CIPHER_CAMELLIA_128_CTR,
+        POLARSSL_CIPHER_CAMELLIA_192_CTR,
+        POLARSSL_CIPHER_CAMELLIA_256_CTR,
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif /* defined(POLARSSL_CAMELLIA_C) */
+
+#if defined(POLARSSL_DES_C)
+        POLARSSL_CIPHER_DES_CBC,
+        POLARSSL_CIPHER_DES_EDE_CBC,
+        POLARSSL_CIPHER_DES_EDE3_CBC,
+#endif /* defined(POLARSSL_DES_C) */
+
+        0
+};
+
+const int *cipher_list( void )
+{
+    return supported_ciphers;
+}
+
+const cipher_info_t *cipher_info_from_type( cipher_type_t cipher_type )
+{
+    /* Find static cipher information */
+    switch ( cipher_type )
+    {
+#if defined(POLARSSL_AES_C)
+        case POLARSSL_CIPHER_AES_128_CBC:
+            return &aes_128_cbc_info;
+        case POLARSSL_CIPHER_AES_192_CBC:
+            return &aes_192_cbc_info;
+        case POLARSSL_CIPHER_AES_256_CBC:
+            return &aes_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+        case POLARSSL_CIPHER_AES_128_CFB128:
+            return &aes_128_cfb128_info;
+        case POLARSSL_CIPHER_AES_192_CFB128:
+            return &aes_192_cfb128_info;
+        case POLARSSL_CIPHER_AES_256_CFB128:
+            return &aes_256_cfb128_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+        case POLARSSL_CIPHER_AES_128_CTR:
+            return &aes_128_ctr_info;
+        case POLARSSL_CIPHER_AES_192_CTR:
+            return &aes_192_ctr_info;
+        case POLARSSL_CIPHER_AES_256_CTR:
+            return &aes_256_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+        case POLARSSL_CIPHER_CAMELLIA_128_CBC:
+            return &camellia_128_cbc_info;
+        case POLARSSL_CIPHER_CAMELLIA_192_CBC:
+            return &camellia_192_cbc_info;
+        case POLARSSL_CIPHER_CAMELLIA_256_CBC:
+            return &camellia_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+        case POLARSSL_CIPHER_CAMELLIA_128_CFB128:
+            return &camellia_128_cfb128_info;
+        case POLARSSL_CIPHER_CAMELLIA_192_CFB128:
+            return &camellia_192_cfb128_info;
+        case POLARSSL_CIPHER_CAMELLIA_256_CFB128:
+            return &camellia_256_cfb128_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+        case POLARSSL_CIPHER_CAMELLIA_128_CTR:
+            return &camellia_128_ctr_info;
+        case POLARSSL_CIPHER_CAMELLIA_192_CTR:
+            return &camellia_192_ctr_info;
+        case POLARSSL_CIPHER_CAMELLIA_256_CTR:
+            return &camellia_256_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif
+
+#if defined(POLARSSL_DES_C)
+        case POLARSSL_CIPHER_DES_CBC:
+            return &des_cbc_info;
+        case POLARSSL_CIPHER_DES_EDE_CBC:
+            return &des_ede_cbc_info;
+        case POLARSSL_CIPHER_DES_EDE3_CBC:
+            return &des_ede3_cbc_info;
+#endif
+
+        default:
+            return NULL;
+    }
+}
+
+const cipher_info_t *cipher_info_from_string( const char *cipher_name )
+{
+    if( NULL == cipher_name )
+        return NULL;
+
+    /* Get the appropriate cipher information */
+#if defined(POLARSSL_CAMELLIA_C)
+    if( !strcasecmp( "CAMELLIA-128-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CBC );
+    if( !strcasecmp( "CAMELLIA-192-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CBC );
+    if( !strcasecmp( "CAMELLIA-256-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CBC );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    if( !strcasecmp( "CAMELLIA-128-CFB128", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CFB128 );
+    if( !strcasecmp( "CAMELLIA-192-CFB128", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CFB128 );
+    if( !strcasecmp( "CAMELLIA-256-CFB128", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CFB128 );
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    if( !strcasecmp( "CAMELLIA-128-CTR", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CTR );
+    if( !strcasecmp( "CAMELLIA-192-CTR", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CTR );
+    if( !strcasecmp( "CAMELLIA-256-CTR", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CTR );
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+#endif
+
+#if defined(POLARSSL_AES_C)
+    if( !strcasecmp( "AES-128-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC );
+    if( !strcasecmp( "AES-192-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CBC );
+    if( !strcasecmp( "AES-256-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CBC );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    if( !strcasecmp( "AES-128-CFB128", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CFB128 );
+    if( !strcasecmp( "AES-192-CFB128", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CFB128 );
+    if( !strcasecmp( "AES-256-CFB128", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CFB128 );
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    if( !strcasecmp( "AES-128-CTR", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CTR );
+    if( !strcasecmp( "AES-192-CTR", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CTR );
+    if( !strcasecmp( "AES-256-CTR", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR );
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+#endif
+
+#if defined(POLARSSL_DES_C)
+    if( !strcasecmp( "DES-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_DES_CBC );
+    if( !strcasecmp( "DES-EDE-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE_CBC );
+    if( !strcasecmp( "DES-EDE3-CBC", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC );
+#endif
+    return NULL;
+}
+
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
+{
+    if( NULL == cipher_info || NULL == ctx )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    memset( ctx, 0, sizeof( ctx ) );
+
+    if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
+        return POLARSSL_ERR_CIPHER_ALLOC_FAILED;
+
+    ctx->cipher_info = cipher_info;
+
+    return 0;
+}
+
+int cipher_free_ctx( cipher_context_t *ctx )
+{
+    if( ctx == NULL || ctx->cipher_info == NULL )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+
+    return 0;
+}
+
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
+        int key_length, const operation_t operation )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    ctx->key_length = key_length;
+    ctx->operation = operation;
+
+    /*
+     * For CFB128 and CTR mode always use the encryption key schedule
+     */
+    if( POLARSSL_ENCRYPT == operation ||
+        POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||
+        POLARSSL_MODE_CTR == ctx->cipher_info->mode )
+    {
+        return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
+                ctx->key_length );
+    }
+
+    if( POLARSSL_DECRYPT == operation )
+        return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
+                ctx->key_length );
+
+    return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+}
+
+int cipher_reset( cipher_context_t *ctx, const unsigned char *iv )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    ctx->unprocessed_len = 0;
+
+    memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
+
+    return 0;
+}
+
+int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
+        unsigned char *output, size_t *olen )
+{
+    int ret;
+    size_t copy_len = 0;
+
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ||
+        input == output )
+    {
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+    *olen = 0;
+
+    if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
+    {
+        /*
+         * If there is not enough data for a full block, cache it.
+         */
+        if( ( ctx->operation == POLARSSL_DECRYPT &&
+                ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) ||
+             ( ctx->operation == POLARSSL_ENCRYPT &&
+                ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) )
+        {
+            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+                    ilen );
+
+            ctx->unprocessed_len += ilen;
+            return 0;
+        }
+
+        /*
+         * Process cached data first
+         */
+        if( ctx->unprocessed_len != 0 )
+        {
+            copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len;
+
+            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+                    copy_len );
+
+            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+                    ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+                    ctx->unprocessed_data, output ) ) )
+            {
+                return ret;
+            }
+
+            *olen += cipher_get_block_size( ctx );
+            output += cipher_get_block_size( ctx );
+            ctx->unprocessed_len = 0;
+
+            input += copy_len;
+            ilen -= copy_len;
+        }
+
+        /*
+         * Cache final, incomplete block
+         */
+        if( 0 != ilen )
+        {
+            copy_len = ilen % cipher_get_block_size( ctx );
+            if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )
+                copy_len = cipher_get_block_size(ctx);
+
+            memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
+                    copy_len );
+
+            ctx->unprocessed_len += copy_len;
+            ilen -= copy_len;
+        }
+
+        /*
+         * Process remaining full blocks
+         */
+        if( ilen )
+        {
+            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+                    ctx->operation, ilen, ctx->iv, input, output ) ) )
+            {
+                return ret;
+            }
+            *olen += ilen;
+        }
+
+        return 0;
+    }
+
+    if( ctx->cipher_info->mode == POLARSSL_MODE_CFB128 )
+    {
+        if( 0 != ( ret = ctx->cipher_info->base->cfb128_func( ctx->cipher_ctx,
+                ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
+                input, output ) ) )
+        {
+            return ret;
+        }
+
+        *olen = ilen;
+
+        return 0;
+    }
+
+    if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
+    {
+        if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
+                ilen, &ctx->unprocessed_len, ctx->iv,
+                ctx->unprocessed_data, input, output ) ) )
+        {
+            return ret;
+        }
+
+        *olen = ilen;
+
+        return 0;
+    }
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+static void add_pkcs_padding( unsigned char *output, size_t output_len,
+        size_t data_len )
+{
+    size_t padding_len = output_len - data_len;
+    unsigned char i = 0;
+
+    for( i = 0; i < padding_len; i++ )
+        output[data_len + i] = (unsigned char) padding_len;
+}
+
+static int get_pkcs_padding( unsigned char *input, unsigned char input_len,
+        size_t *data_len)
+{
+    int i = 0;
+    unsigned char padding_len = 0;
+
+    if( NULL == input || NULL == data_len )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    padding_len = input[input_len - 1];
+
+    if( padding_len > input_len )
+        return POLARSSL_ERR_CIPHER_INVALID_PADDING;
+
+    for( i = input_len - padding_len; i < input_len; i++ )
+        if( input[i] != padding_len )
+            return POLARSSL_ERR_CIPHER_INVALID_PADDING;
+
+    *data_len = input_len - padding_len;
+
+    return 0;
+}
+
+int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen)
+{
+    int ret = 0;
+
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    *olen = 0;
+
+    if( POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||
+        POLARSSL_MODE_CTR == ctx->cipher_info->mode )
+    {
+        return 0;
+    }
+
+    if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
+    {
+        if( POLARSSL_ENCRYPT == ctx->operation )
+        {
+            add_pkcs_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),
+                    ctx->unprocessed_len );
+        }
+        else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
+        {
+            /* For decrypt operations, expect a full block */
+            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+        }
+
+        /* cipher block */
+        if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+                ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+                ctx->unprocessed_data, output ) ) )
+        {
+            return ret;
+        }
+
+        /* Set output size for decryption */
+        if( POLARSSL_DECRYPT == ctx->operation )
+            return get_pkcs_padding( output, cipher_get_block_size( ctx ), olen );
+
+        /* Set output size for encryption */
+        *olen = cipher_get_block_size( ctx );
+        return 0;
+    }
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+
+#define ASSERT(x) if (!(x)) { \
+        printf( "failed with %i at %s\n", value, (#x) ); \
+    return( 1 ); \
+}
+/*
+ * Checkup routine
+ */
+
+int cipher_self_test( int verbose )
+{
+    ((void) verbose);
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 552 - 0
thirdparty/PolarSSL/library/cipher_wrap.c

@@ -0,0 +1,552 @@
+/**
+ * \file md_wrap.c
+ * 
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher_wrap.h"
+#include "polarssl/aes.h"
+#include "polarssl/camellia.h"
+#include "polarssl/des.h"
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_AES_C)
+
+int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, output );
+}
+
+int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+        size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, input, output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv_off);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int aes_crypt_ctr_wrap( void *ctx, size_t length,
+        size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter,
+                          stream_block, input, output );
+#else
+    ((void) ctx);
+    ((void) length);
+    ((void) nc_off);
+    ((void) nonce_counter);
+    ((void) stream_block);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    return aes_setkey_dec( (aes_context *) ctx, key, key_length );
+}
+
+int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    return aes_setkey_enc( (aes_context *) ctx, key, key_length );
+}
+
+static void * aes_ctx_alloc( void )
+{
+    return malloc( sizeof( aes_context ) );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const cipher_base_t aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    aes_crypt_cbc_wrap,
+    aes_crypt_cfb128_wrap,
+    aes_crypt_ctr_wrap,
+    aes_setkey_enc_wrap,
+    aes_setkey_dec_wrap,
+    aes_ctx_alloc,
+    aes_ctx_free
+};
+
+const cipher_info_t aes_128_cbc_info = {
+    POLARSSL_CIPHER_AES_128_CBC,
+    POLARSSL_MODE_CBC,
+    128,
+    "AES-128-CBC",
+    16,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_cbc_info = {
+    POLARSSL_CIPHER_AES_192_CBC,
+    POLARSSL_MODE_CBC,
+    192,
+    "AES-192-CBC",
+    16,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_cbc_info = {
+    POLARSSL_CIPHER_AES_256_CBC,
+    POLARSSL_MODE_CBC,
+    256,
+    "AES-256-CBC",
+    16,
+    16,
+    &aes_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t aes_128_cfb128_info = {
+    POLARSSL_CIPHER_AES_128_CFB128,
+    POLARSSL_MODE_CFB128,
+    128,
+    "AES-128-CFB128",
+    16,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_cfb128_info = {
+    POLARSSL_CIPHER_AES_192_CFB128,
+    POLARSSL_MODE_CFB128,
+    192,
+    "AES-192-CFB128",
+    16,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_cfb128_info = {
+    POLARSSL_CIPHER_AES_256_CFB128,
+    POLARSSL_MODE_CFB128,
+    256,
+    "AES-256-CFB128",
+    16,
+    16,
+    &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t aes_128_ctr_info = {
+    POLARSSL_CIPHER_AES_128_CTR,
+    POLARSSL_MODE_CTR,
+    128,
+    "AES-128-CTR",
+    16,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_ctr_info = {
+    POLARSSL_CIPHER_AES_192_CTR,
+    POLARSSL_MODE_CTR,
+    192,
+    "AES-192-CTR",
+    16,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_ctr_info = {
+    POLARSSL_CIPHER_AES_256_CTR,
+    POLARSSL_MODE_CTR,
+    256,
+    "AES-256-CTR",
+    16,
+    16,
+    &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, input, output );
+}
+
+int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+        size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, iv_off, iv, input, output );
+#else
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv_off);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int camellia_crypt_ctr_wrap( void *ctx, size_t length,
+        size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+        const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, nonce_counter,
+                          stream_block, input, output );
+#else
+    ((void) ctx);
+    ((void) length);
+    ((void) nc_off);
+    ((void) nonce_counter);
+    ((void) stream_block);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    return camellia_setkey_dec( (camellia_context *) ctx, key, key_length );
+}
+
+int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    return camellia_setkey_enc( (camellia_context *) ctx, key, key_length );
+}
+
+static void * camellia_ctx_alloc( void )
+{
+    return malloc( sizeof( camellia_context ) );
+}
+
+static void camellia_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const cipher_base_t camellia_info = {
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    camellia_crypt_cbc_wrap,
+    camellia_crypt_cfb128_wrap,
+    camellia_crypt_ctr_wrap,
+    camellia_setkey_enc_wrap,
+    camellia_setkey_dec_wrap,
+    camellia_ctx_alloc,
+    camellia_ctx_free
+};
+
+const cipher_info_t camellia_128_cbc_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CBC,
+    POLARSSL_MODE_CBC,
+    128,
+    "CAMELLIA-128-CBC",
+    16,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_cbc_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CBC,
+    POLARSSL_MODE_CBC,
+    192,
+    "CAMELLIA-192-CBC",
+    16,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_cbc_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CBC,
+    POLARSSL_MODE_CBC,
+    256,
+    "CAMELLIA-256-CBC",
+    16,
+    16,
+    &camellia_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t camellia_128_cfb128_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+    POLARSSL_MODE_CFB128,
+    128,
+    "CAMELLIA-128-CFB128",
+    16,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_cfb128_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+    POLARSSL_MODE_CFB128,
+    192,
+    "CAMELLIA-192-CFB128",
+    16,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_cfb128_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+    POLARSSL_MODE_CFB128,
+    256,
+    "CAMELLIA-256-CFB128",
+    16,
+    16,
+    &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t camellia_128_ctr_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CTR,
+    POLARSSL_MODE_CTR,
+    128,
+    "CAMELLIA-128-CTR",
+    16,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_ctr_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CTR,
+    POLARSSL_MODE_CTR,
+    192,
+    "CAMELLIA-192-CTR",
+    16,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_ctr_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CTR,
+    POLARSSL_MODE_CTR,
+    256,
+    "CAMELLIA-256-CTR",
+    16,
+    16,
+    &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif
+
+#if defined(POLARSSL_DES_C)
+
+int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, output );
+}
+
+int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, output );
+}
+
+int des_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+        size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    ((void) ctx);
+    ((void) operation);
+    ((void) length);
+    ((void) iv_off);
+    ((void) iv);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+int des_crypt_ctr_wrap( void *ctx, size_t length,
+        size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+        const unsigned char *input, unsigned char *output )
+{
+    ((void) ctx);
+    ((void) length);
+    ((void) nc_off);
+    ((void) nonce_counter);
+    ((void) stream_block);
+    ((void) input);
+    ((void) output);
+
+    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+
+int des_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des_setkey_dec( (des_context *) ctx, key );
+}
+
+int des_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des_setkey_enc( (des_context *) ctx, key );
+}
+
+int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set2key_dec( (des3_context *) ctx, key );
+}
+
+int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set2key_enc( (des3_context *) ctx, key );
+}
+
+int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set3key_dec( (des3_context *) ctx, key );
+}
+
+int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    ((void) key_length);
+
+    return des3_set3key_enc( (des3_context *) ctx, key );
+}
+
+static void * des_ctx_alloc( void )
+{
+    return malloc( sizeof( des_context ) );
+}
+
+static void * des3_ctx_alloc( void )
+{
+    return malloc( sizeof( des3_context ) );
+}
+
+static void des_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const cipher_base_t des_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des_crypt_cbc_wrap,
+    des_crypt_cfb128_wrap,
+    des_crypt_ctr_wrap,
+    des_setkey_enc_wrap,
+    des_setkey_dec_wrap,
+    des_ctx_alloc,
+    des_ctx_free
+};
+
+const cipher_info_t des_cbc_info = {
+    POLARSSL_CIPHER_DES_CBC,
+    POLARSSL_MODE_CBC,
+    POLARSSL_KEY_LENGTH_DES,
+    "DES-CBC",
+    8,
+    8,
+    &des_info
+};
+
+const cipher_base_t des_ede_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des3_crypt_cbc_wrap,
+    des_crypt_cfb128_wrap,
+    des_crypt_ctr_wrap,
+    des3_set2key_enc_wrap,
+    des3_set2key_dec_wrap,
+    des3_ctx_alloc,
+    des_ctx_free
+};
+
+const cipher_info_t des_ede_cbc_info = {
+    POLARSSL_CIPHER_DES_EDE_CBC,
+    POLARSSL_MODE_CBC,
+    POLARSSL_KEY_LENGTH_DES_EDE,
+    "DES-EDE-CBC",
+    16,
+    16,
+    &des_ede_info
+};
+
+const cipher_base_t des_ede3_info = {
+    POLARSSL_CIPHER_ID_DES,
+    des3_crypt_cbc_wrap,
+    des_crypt_cfb128_wrap,
+    des_crypt_ctr_wrap,
+    des3_set3key_enc_wrap,
+    des3_set3key_dec_wrap,
+    des3_ctx_alloc,
+    des_ctx_free
+};
+
+const cipher_info_t des_ede3_cbc_info = {
+    POLARSSL_CIPHER_DES_EDE3_CBC,
+    POLARSSL_MODE_CBC,
+    POLARSSL_KEY_LENGTH_DES_EDE3,
+    "DES-EDE3-CBC",
+    8,
+    8,
+    &des_ede3_info
+};
+#endif
+
+#endif

+ 238 - 0
thirdparty/PolarSSL/library/debug.c

@@ -0,0 +1,238 @@
+/*
+ *  Debugging routines
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_DEBUG_C)
+
+#include "polarssl/debug.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#if defined _MSC_VER && !defined  snprintf
+#define  snprintf  _snprintf
+#endif
+
+#if defined _MSC_VER && !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+
+char *debug_fmt( const char *format, ... )
+{
+    va_list argp;
+    static char str[512];
+    int maxlen = sizeof( str ) - 1;
+
+    va_start( argp, format );
+    vsnprintf( str, maxlen, format, argp );
+    va_end( argp );
+
+    str[maxlen] = '\0';
+    return( str );
+}
+
+void debug_print_msg( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text )
+{
+    char str[512];
+    int maxlen = sizeof( str ) - 1;
+
+    if( ssl->f_dbg == NULL )
+        return;
+
+    snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text );
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_ret( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, int ret )
+{
+    char str[512];
+    int maxlen = sizeof( str ) - 1;
+
+    if( ssl->f_dbg == NULL )
+        return;
+
+    snprintf( str, maxlen, "%s(%04d): %s() returned %d (0x%x)\n",
+              file, line, text, ret, ret );
+
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_buf( const ssl_context *ssl, int level,
+                      const char *file, int line, const char *text,
+                      unsigned char *buf, size_t len )
+{
+    char str[512];
+    size_t i, maxlen = sizeof( str ) - 1;
+
+    if( ssl->f_dbg == NULL )
+        return;
+
+    snprintf( str, maxlen, "%s(%04d): dumping '%s' (%d bytes)\n",
+              file, line, text, (unsigned int) len );
+
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+
+    for( i = 0; i < len; i++ )
+    {
+        if( i >= 4096 )
+            break;
+
+        if( i % 16 == 0 )
+        {
+            if( i > 0 )
+                ssl->f_dbg( ssl->p_dbg, level, "\n" );
+
+            snprintf( str, maxlen, "%s(%04d): %04x: ", file, line,
+                      (unsigned int) i );
+
+            str[maxlen] = '\0';
+            ssl->f_dbg( ssl->p_dbg, level, str );
+        }
+
+        snprintf( str, maxlen, " %02x", (unsigned int) buf[i] );
+
+        str[maxlen] = '\0';
+        ssl->f_dbg( ssl->p_dbg, level, str );
+    }
+
+    if( len > 0 )
+        ssl->f_dbg( ssl->p_dbg, level, "\n" );
+}
+
+void debug_print_mpi( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const mpi *X )
+{
+    char str[512];
+    int j, k, maxlen = sizeof( str ) - 1, zeros = 1;
+    size_t i, n;
+
+    if( ssl->f_dbg == NULL || X == NULL )
+        return;
+
+    for( n = X->n - 1; n > 0; n-- )
+        if( X->p[n] != 0 )
+            break;
+
+    for( j = ( sizeof(t_uint) << 3 ) - 1; j >= 0; j-- )
+        if( ( ( X->p[n] >> j ) & 1 ) != 0 )
+            break;
+
+    snprintf( str, maxlen, "%s(%04d): value of '%s' (%lu bits) is:\n",
+              file, line, text, 
+              (unsigned long) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) );
+
+    str[maxlen] = '\0';
+    ssl->f_dbg( ssl->p_dbg, level, str );
+
+    for( i = n + 1, j = 0; i > 0; i-- )
+    {
+        if( zeros && X->p[i - 1] == 0 )
+            continue;
+
+        for( k = sizeof( t_uint ) - 1; k >= 0; k-- )
+        {
+            if( zeros && ( ( X->p[i - 1] >> (k << 3) ) & 0xFF ) == 0 )
+                continue;
+            else
+                zeros = 0;
+
+            if( j % 16 == 0 )
+            {
+                if( j > 0 )
+                    ssl->f_dbg( ssl->p_dbg, level, "\n" );
+
+                snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+                str[maxlen] = '\0';
+                ssl->f_dbg( ssl->p_dbg, level, str );
+            }
+
+            snprintf( str, maxlen, " %02x", (unsigned int)
+                      ( X->p[i - 1] >> (k << 3) ) & 0xFF );
+
+            str[maxlen] = '\0';
+            ssl->f_dbg( ssl->p_dbg, level, str );
+
+            j++;
+        }
+
+    }
+
+    if( zeros == 1 )
+    {
+        snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+        str[maxlen] = '\0';
+        ssl->f_dbg( ssl->p_dbg, level, str );
+        ssl->f_dbg( ssl->p_dbg, level, " 00" );
+    }
+
+    ssl->f_dbg( ssl->p_dbg, level, "\n" );
+}
+
+void debug_print_crt( const ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const x509_cert *crt )
+{
+    char str[1024], prefix[64];
+    int i = 0, maxlen = sizeof( prefix ) - 1;
+
+    if( ssl->f_dbg == NULL || crt == NULL )
+        return;
+
+    snprintf( prefix, maxlen, "%s(%04d): ", file, line );
+    prefix[maxlen] = '\0';
+    maxlen = sizeof( str ) - 1;
+
+    while( crt != NULL )
+    {
+        char buf[1024];
+        x509parse_cert_info( buf, sizeof( buf ) - 1, prefix, crt );
+
+        snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s",
+                  file, line, text, ++i, buf );
+
+        str[maxlen] = '\0';
+        ssl->f_dbg( ssl->p_dbg, level, str );
+
+        debug_print_mpi( ssl, level, file, line,
+                         "crt->rsa.N", &crt->rsa.N );
+
+        debug_print_mpi( ssl, level, file, line,
+                         "crt->rsa.E", &crt->rsa.E );
+
+        crt = crt->next;
+    }
+}
+
+#endif

+ 1255 - 0
thirdparty/PolarSSL/library/des.c

@@ -0,0 +1,1255 @@
+/*
+ *  FIPS-46-3 compliant Triple-DES implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  DES, on which TDES is based, was originally designed by Horst Feistel
+ *  at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
+ *
+ *  http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
+ */
+
+/* Note: This file has been modified by ST's MCD Application Team, to support 
+   the hardware crypto engine embedded in STM32F417xx */
+
+#include "config.h"
+
+#if defined(POLARSSL_DES_C)
+#include "main.h"
+#include "polarssl/des.h"
+
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */ 
+CRYP_InitTypeDef DES3_CRYP_InitStructure;
+CRYP_KeyInitTypeDef DES3_CRYP_KeyInitStructure;
+CRYP_IVInitTypeDef DES3_CRYP_IVInitStructure;
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
+        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 3]       );       \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * Expanded DES S-boxes
+ */
+static const unsigned long SB1[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
+};
+
+static const unsigned long SB2[64] =
+{
+    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
+};
+
+static const unsigned long SB3[64] =
+{
+    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
+};
+
+static const unsigned long SB4[64] =
+{
+    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
+};
+
+static const unsigned long SB5[64] =
+{
+    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
+};
+
+static const unsigned long SB6[64] =
+{
+    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
+};
+
+static const unsigned long SB7[64] =
+{
+    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
+};
+
+static const unsigned long SB8[64] =
+{
+    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
+};
+
+/*
+ * PC1: left and right halves bit-swap
+ */
+static const unsigned long LHs[16] =
+{
+    0x00000000, 0x00000001, 0x00000100, 0x00000101,
+    0x00010000, 0x00010001, 0x00010100, 0x00010101,
+    0x01000000, 0x01000001, 0x01000100, 0x01000101,
+    0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const unsigned long RHs[16] =
+{
+    0x00000000, 0x01000000, 0x00010000, 0x01010000,
+    0x00000100, 0x01000100, 0x00010100, 0x01010100,
+    0x00000001, 0x01000001, 0x00010001, 0x01010001,
+    0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/*
+ * Initial Permutation macro
+ */
+#define DES_IP(X,Y)                                             \
+{                                                               \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T;                   \
+    X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF;                    \
+}
+
+/*
+ * Final Permutation macro
+ */
+#define DES_FP(X,Y)                                             \
+{                                                               \
+    X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T;                   \
+    Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF;                    \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+}
+
+/*
+ * DES round macro
+ */
+#define DES_ROUND(X,Y)                          \
+{                                               \
+    T = *SK++ ^ X;                              \
+    Y ^= SB8[ (T      ) & 0x3F ] ^              \
+         SB6[ (T >>  8) & 0x3F ] ^              \
+         SB4[ (T >> 16) & 0x3F ] ^              \
+         SB2[ (T >> 24) & 0x3F ];               \
+                                                \
+    T = *SK++ ^ ((X << 28) | (X >> 4));         \
+    Y ^= SB7[ (T      ) & 0x3F ] ^              \
+         SB5[ (T >>  8) & 0x3F ] ^              \
+         SB3[ (T >> 16) & 0x3F ] ^              \
+         SB1[ (T >> 24) & 0x3F ];               \
+}
+
+#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
+
+static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
+        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+        254 };
+
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        if ( key[i] != odd_parity_table[key[i] / 2] )
+            return( 1 );
+
+    return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
+{
+    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < WEAK_KEY_COUNT; i++ )
+        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0)
+            return( 1 );
+
+    return( 0 );
+}
+
+static void des_setkey( unsigned long SK[32], const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+    unsigned long X, Y, T;
+
+    GET_ULONG_BE( X, key, 0 );
+    GET_ULONG_BE( Y, key, 4 );
+
+    /*
+     * Permuted Choice 1
+     */
+    T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);
+    T =  ((Y      ) ^ X) & 0x10101010;  X ^= T; Y ^= (T      );
+
+    X =   (LHs[ (X      ) & 0xF] << 3) | (LHs[ (X >>  8) & 0xF ] << 2)
+        | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ]     )
+        | (LHs[ (X >>  5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+        | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+    Y =   (RHs[ (Y >>  1) & 0xF] << 3) | (RHs[ (Y >>  9) & 0xF ] << 2)
+        | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ]     )
+        | (RHs[ (Y >>  4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+        | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+    X &= 0x0FFFFFFF;
+    Y &= 0x0FFFFFFF;
+
+    /*
+     * calculate subkeys
+     */
+    for( i = 0; i < 16; i++ )
+    {
+        if( i < 2 || i == 8 || i == 15 )
+        {
+            X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;
+            Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;
+        }
+        else
+        {
+            X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;
+            Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;
+        }
+
+        *SK++ =   ((X <<  4) & 0x24000000) | ((X << 28) & 0x10000000)
+                | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+                | ((X <<  6) & 0x01000000) | ((X <<  9) & 0x00200000)
+                | ((X >>  1) & 0x00100000) | ((X << 10) & 0x00040000)
+                | ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)
+                | ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)
+                | ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)
+                | ((Y >> 14) & 0x00000200) | ((Y      ) & 0x00000100)
+                | ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+                | ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+                | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+        *SK++ =   ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+                | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+                | ((X >>  2) & 0x02000000) | ((X <<  1) & 0x01000000)
+                | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+                | ((X <<  3) & 0x00080000) | ((X >>  6) & 0x00040000)
+                | ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)
+                | ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)
+                | ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)
+                | ((Y      ) & 0x00000200) | ((Y <<  7) & 0x00000100)
+                | ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)
+                | ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+    }
+}
+
+/*
+ * DES key schedule (56-bit, encryption)
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+    des_setkey( ctx->sk, key );
+
+    return( 0 );
+}
+
+/*
+ * DES key schedule (56-bit, decryption)
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    des_setkey( ctx->sk, key );
+
+    for( i = 0; i < 16; i += 2 )
+    {
+        SWAP( ctx->sk[i    ], ctx->sk[30 - i] );
+        SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+    }
+
+    return( 0 );
+}
+
+static void des3_set2key( unsigned long esk[96],
+                          unsigned long dsk[96],
+                          const unsigned char key[DES_KEY_SIZE*2] )
+{
+    int i;
+
+    des_setkey( esk, key );
+    des_setkey( dsk + 32, key + 8 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[30 - i];
+        dsk[i +  1] = esk[31 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        esk[i + 64] = esk[i    ];
+        esk[i + 65] = esk[i + 1];
+
+        dsk[i + 64] = dsk[i    ];
+        dsk[i + 65] = dsk[i + 1];
+    }
+}
+
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+{
+    unsigned long sk[96];
+
+    des3_set2key( ctx->sk, sk, key );
+    memset( sk,  0, sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+{
+    unsigned long sk[96];
+
+    des3_set2key( sk, ctx->sk, key );
+    memset( sk,  0, sizeof( sk ) );
+
+    return( 0 );
+}
+
+#ifndef USE_STM32F4XX_HW_CRYPTO /* use SW Crypto */
+static void des3_set3key( unsigned long esk[96],
+                          unsigned long dsk[96],
+                          const unsigned char key[24] )
+{
+    int i;
+
+    des_setkey( esk, key );
+    des_setkey( dsk + 32, key +  8 );
+    des_setkey( esk + 64, key + 16 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[94 - i];
+        dsk[i +  1] = esk[95 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        dsk[i + 64] = esk[30 - i];
+        dsk[i + 65] = esk[31 - i];
+    }
+}
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  memcpy(ctx->tdes_enc_key, key, 24);
+
+#else /* use SW Crypto */
+    unsigned long sk[96];
+
+    des3_set3key( ctx->sk, sk, key );
+    memset( sk, 0, sizeof( sk ) );
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  memcpy(ctx->tdes_dec_key, key, 24);
+
+#else /* use SW Crypto */
+    unsigned long sk[96];
+
+    des3_set3key( sk, ctx->sk, key );
+    memset( sk, 0, sizeof( sk ) );
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+    return( 0 );
+}
+
+/*
+ * DES-ECB block encryption/decryption
+ */
+int des_crypt_ecb( des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] )
+{
+    int i;
+    unsigned long X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_ULONG_BE( X, input, 0 );
+    GET_ULONG_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_ULONG_BE( Y, output, 0 );
+    PUT_ULONG_BE( X, output, 4 );
+
+    return( 0 );
+}
+
+/*
+ * DES-CBC buffer encryption/decryption
+ */
+int des_crypt_cbc( des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == DES_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            des_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* DES_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            des_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * 3DES-ECB block encryption/decryption
+ */
+int des3_crypt_ecb( des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  unsigned char *tdeskey; /* 3DES encryption/decryption key */
+
+  if( ctx->mode == DES_ENCRYPT ) /* 3DES encryption */
+  {
+    /* Encryption key */
+    tdeskey = ctx->tdes_enc_key;
+  
+    /* Deinitializes the CRYP peripheral */  
+    CRYP_DeInit();
+ 
+    /* Crypto structures initialisation*/
+    CRYP_StructInit(&DES3_CRYP_InitStructure);  
+    CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure);
+
+    /* Crypto Init for Encryption process */      
+    DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+    DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_ECB;
+    DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    CRYP_Init(&DES3_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&tdeskey[0]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&tdeskey[4]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&tdeskey[8]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&tdeskey[12]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&tdeskey[16]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&tdeskey[20]);
+    CRYP_KeyInit(& DES3_CRYP_KeyInitStructure);
+
+    /* Flush IN/OUT FIFO */
+    CRYP_FIFOFlush();
+
+    /* Write the input block in the input FIFO */
+    CRYP_DataIn(*(uint32_t*)&input[0]);
+    CRYP_DataIn(*(uint32_t*)&input[4]);
+
+    /* Enable Crypto processor */
+    CRYP_Cmd(ENABLE);
+
+    /* Wait until the complete message has been processed */ 
+    while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY)!= RESET);
+   
+    /* Read the output block from the output FIFO */
+    *(uint32_t*)&output[0] = CRYP_DataOut();
+    *(uint32_t*)&output[4] = CRYP_DataOut();
+  
+    /* Disable Crypto */
+    CRYP_Cmd(DISABLE);
+  }
+  else if( ctx->mode == DES_DECRYPT ) /* 3DES decryption */
+  {
+    /* Decryption key */
+    tdeskey = ctx->tdes_dec_key;
+  
+    /* Deinitializes the CRYP peripheral */  
+    CRYP_DeInit();
+ 
+    /* Crypto structures initialisation*/
+    CRYP_StructInit(&DES3_CRYP_InitStructure);  
+    CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure);
+
+    /* Crypto Init for Encryption process */      
+    DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+    DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_ECB;
+    DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    CRYP_Init(&DES3_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&tdeskey[0]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&tdeskey[4]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&tdeskey[8]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&tdeskey[12]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&tdeskey[16]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&tdeskey[20]);
+    CRYP_KeyInit(& DES3_CRYP_KeyInitStructure);
+
+    /* Flush IN/OUT FIFO */
+    CRYP_FIFOFlush();
+
+    /* Write the input block in the input FIFO */
+    CRYP_DataIn(*(uint32_t*)&input[0]);
+    CRYP_DataIn(*(uint32_t*)&input[4]);
+
+    /* Enable Crypto processor */
+    CRYP_Cmd(ENABLE);
+
+    /* Wait until the complete message has been processed */ 
+    while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY)!= RESET);
+   
+    /* Read the output block from the output FIFO */
+    *(uint32_t*)&output[0] = CRYP_DataOut();
+    *(uint32_t*)&output[4] = CRYP_DataOut();
+  
+    /* Disable Crypto */
+    CRYP_Cmd(DISABLE);
+  }
+
+#else /* use SW Crypto */
+    int i;
+    unsigned long X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_ULONG_BE( X, input, 0 );
+    GET_ULONG_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( X, Y );
+        DES_ROUND( Y, X );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_ULONG_BE( Y, output, 0 );
+    PUT_ULONG_BE( X, output, 4 );
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+    return( 0 );
+}
+
+/*
+ * 3DES-CBC buffer encryption/decryption
+ */
+int des3_crypt_cbc( des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  unsigned char *tdeskey; /* 3DES encryption/decryption key */
+
+  if( mode == DES_ENCRYPT ) /* 3DES encryption */
+  {
+    ctx->mode = DES_ENCRYPT; 
+
+    /* Encryption key */
+    tdeskey = ctx->tdes_enc_key;
+  
+    /* Deinitializes the CRYP peripheral */  
+    CRYP_DeInit();
+ 
+    /* Crypto structures initialisation*/
+    CRYP_StructInit(&DES3_CRYP_InitStructure);  
+    CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure);
+    CRYP_IVStructInit(&DES3_CRYP_IVInitStructure);
+
+    /* Crypto Init for Encryption process */      
+    DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Encrypt;
+    DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC;
+    DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    CRYP_Init(&DES3_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&tdeskey[0]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&tdeskey[4]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&tdeskey[8]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&tdeskey[12]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&tdeskey[16]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&tdeskey[20]);
+    CRYP_KeyInit(& DES3_CRYP_KeyInitStructure);
+
+    /* Initialization Vectors */
+    DES3_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)&iv[0]);
+    DES3_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)&iv[4]);
+    CRYP_IVInit(&DES3_CRYP_IVInitStructure);
+
+    while(length > 0)
+    {
+      /* Flush IN/OUT FIFO */
+      CRYP_FIFOFlush();
+
+      /* Write the input block in the input FIFO */
+      CRYP_DataIn(*(uint32_t*)&input[0]);
+      CRYP_DataIn(*(uint32_t*)&input[4]);
+
+      /* Enable Crypto processor */
+      CRYP_Cmd(ENABLE);
+
+      /* Wait until the complete message has been processed */ 
+      while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY)!= RESET);
+   
+      /* Read the output block from the output FIFO */
+      *(uint32_t*)&output[0] = CRYP_DataOut();
+      *(uint32_t*)&output[4] = CRYP_DataOut();
+      
+      /* Update the initialization Vector */
+      memcpy(iv, output, 8);
+      
+      input  += 8;
+      output += 8;
+      length -= 8; 
+    }
+    /* Disable Crypto */
+    CRYP_Cmd(DISABLE);
+  }
+  else /* 3DES decryption */
+  {
+    ctx->mode = DES_DECRYPT; 
+      
+    /* Decryption key */
+    tdeskey = ctx->tdes_dec_key;
+  
+    /* Deinitializes the CRYP peripheral */  
+    CRYP_DeInit();
+ 
+    /* Crypto structures initialisation*/
+    CRYP_StructInit(&DES3_CRYP_InitStructure);  
+    CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure);
+    CRYP_IVStructInit(&DES3_CRYP_IVInitStructure);
+
+    /* Crypto Init for Encryption process */      
+    DES3_CRYP_InitStructure.CRYP_AlgoDir  = CRYP_AlgoDir_Decrypt;
+    DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC;
+    DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b;
+    CRYP_Init(&DES3_CRYP_InitStructure);
+
+    /* Key Initialisation */
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Left = __REV(*(uint32_t*)&tdeskey[0]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key1Right= __REV(*(uint32_t*)&tdeskey[4]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Left = __REV(*(uint32_t*)&tdeskey[8]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key2Right= __REV(*(uint32_t*)&tdeskey[12]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Left = __REV(*(uint32_t*)&tdeskey[16]);
+    DES3_CRYP_KeyInitStructure.CRYP_Key3Right= __REV(*(uint32_t*)&tdeskey[20]);
+    CRYP_KeyInit(& DES3_CRYP_KeyInitStructure);
+
+    /* Initialization Vectors */
+    DES3_CRYP_IVInitStructure.CRYP_IV0Left = __REV(*(uint32_t*)&iv[0]);
+    DES3_CRYP_IVInitStructure.CRYP_IV0Right= __REV(*(uint32_t*)&iv[4]);
+    CRYP_IVInit(&DES3_CRYP_IVInitStructure);
+
+    while(length > 0)
+    {
+      /* Update the initialization Vector */
+      memcpy(iv, input, 8);
+      
+      /* Flush IN/OUT FIFO */
+      CRYP_FIFOFlush();
+
+      /* Write the input block in the input FIFO */
+      CRYP_DataIn(*(uint32_t*)&input[0]);
+      CRYP_DataIn(*(uint32_t*)&input[4]);
+
+      /* Enable Crypto processor */
+      CRYP_Cmd(ENABLE);
+
+      /* Wait until the complete message has been processed */ 
+      while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY)!= RESET);
+   
+      /* Read the output block from the output FIFO */
+      *(uint32_t*)&output[0] = CRYP_DataOut();
+      *(uint32_t*)&output[4] = CRYP_DataOut();
+
+      input  += 8;
+      output += 8;
+      length -= 8; 
+    }
+    /* Disable Crypto */
+    CRYP_Cmd(DISABLE);
+  }
+
+#else /* use SW Crypto */
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == DES_ENCRYPT )
+    {
+        ctx->mode = DES_ENCRYPT; /* Added by ST's MCD Application Team */    
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            des3_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* DES_DECRYPT */
+    {
+        ctx->mode = DES_DECRYPT; /* Added by ST's MCD Application Team */
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            des3_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+    return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+
+/*
+ * DES and 3DES test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+ */
+static const unsigned char des3_test_keys[24] =
+{
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+    0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+    0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_iv[8] =
+{
+    0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+    0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+    { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+    { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+    { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+    { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+    { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+    { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+    { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+    { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+    { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+    { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+    { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+    { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+
+/*
+ * Checkup routine
+ */
+int des_self_test( int verbose )
+{
+    int i, j, u, v;
+    des_context ctx;
+    des3_context ctx3;
+    unsigned char key[24];
+    unsigned char buf[8];
+    unsigned char prv[8];
+    unsigned char iv[8];
+
+    memset( key, 0, 24 );
+
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  DES%c-ECB-%3d (%s): ",
+                    ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                    ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
+            break;
+
+        case 1:
+            des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
+            break;
+
+        case 2:
+            des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        case 3:
+            des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        case 4:
+            des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        case 5:
+            des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        for( j = 0; j < 10000; j++ )
+        {
+            if( u == 0 )
+                des_crypt_ecb( &ctx, buf, buf );
+            else
+                des3_crypt_ecb( &ctx3, buf, buf );
+        }
+
+        if( ( v == DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+            ( v != DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    /*
+     * CBC mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            printf( "  DES%c-CBC-%3d (%s): ",
+                    ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                    ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  des3_test_iv,  8 );
+        memcpy( prv, des3_test_iv,  8 );
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
+            break;
+
+        case 1:
+            des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
+            break;
+
+        case 2:
+            des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        case 3:
+            des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        case 4:
+            des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        case 5:
+            des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        if( v == DES_DECRYPT )
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                if( u == 0 )
+                    des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+            }
+        }
+        else
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                unsigned char tmp[8];
+
+                if( u == 0 )
+                    des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+                memcpy( tmp, prv, 8 );
+                memcpy( prv, buf, 8 );
+                memcpy( buf, tmp, 8 );
+            }
+
+            memcpy( buf, prv, 8 );
+        }
+
+        if( ( v == DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+            ( v != DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 290 - 0
thirdparty/PolarSSL/library/dhm.c

@@ -0,0 +1,290 @@
+/*
+ *  Diffie-Hellman-Merkle key exchange
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  Reference:
+ *
+ *  http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_DHM_C)
+
+#include "polarssl/dhm.h"
+
+/*
+ * helper to validate the mpi size and import it
+ */
+static int dhm_read_bignum( mpi *X,
+                            unsigned char **p,
+                            const unsigned char *end )
+{
+    int ret, n;
+
+    if( end - *p < 2 )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    n = ( (*p)[0] << 8 ) | (*p)[1];
+    (*p) += 2;
+
+    if( (int)( end - *p ) < n )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
+        return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret );
+
+    (*p) += n;
+
+    return( 0 );
+}
+
+/*
+ * Verify sanity of public parameter with regards to P
+ *
+ * Public parameter should be: 2 <= public_param <= P - 2
+ *
+ * For more information on the attack, see:
+ *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
+ *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
+ */
+static int dhm_check_range( const mpi *public_param, const mpi *P )
+{
+    mpi L, U;
+    int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA;
+
+    mpi_init( &L ); mpi_init( &U );
+    mpi_lset( &L, 2 );
+    mpi_sub_int( &U, P, 2 );
+
+    if( mpi_cmp_mpi( public_param, &L ) >= 0 &&
+        mpi_cmp_mpi( public_param, &U ) <= 0 )
+    {
+        ret = 0;
+    }
+
+    mpi_free( &L ); mpi_free( &U );
+
+    return( ret );
+}
+
+/*
+ * Parse the ServerKeyExchange parameters
+ */
+int dhm_read_params( dhm_context *ctx,
+                     unsigned char **p,
+                     const unsigned char *end )
+{
+    int ret, n;
+
+    memset( ctx, 0, sizeof( dhm_context ) );
+
+    if( ( ret = dhm_read_bignum( &ctx->P,  p, end ) ) != 0 ||
+        ( ret = dhm_read_bignum( &ctx->G,  p, end ) ) != 0 ||
+        ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
+        return( ret );
+
+    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+        return( ret );
+
+    ctx->len = mpi_size( &ctx->P );
+
+    if( end - *p < 2 )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    n = ( (*p)[0] << 8 ) | (*p)[1];
+    (*p) += 2;
+
+    if( end != *p + n )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    return( 0 );
+}
+
+/*
+ * Setup and write the ServerKeyExchange parameters
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *), void *p_rng )
+{
+    int ret, n;
+    size_t n1, n2, n3;
+    unsigned char *p;
+
+    /*
+     * Generate X as large as possible ( < P )
+     */
+    n = x_size / sizeof( t_uint ) + 1;
+
+    mpi_fill_random( &ctx->X, n, f_rng, p_rng );
+
+    while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+           mpi_shift_r( &ctx->X, 1 );
+
+    /*
+     * Calculate GX = G^X mod P
+     */
+    MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+                          &ctx->P , &ctx->RP ) );
+
+    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+        return( ret );
+
+    /*
+     * export P, G, GX
+     */
+#define DHM_MPI_EXPORT(X,n)                     \
+    MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
+    *p++ = (unsigned char)( n >> 8 );           \
+    *p++ = (unsigned char)( n      ); p += n;
+
+    n1 = mpi_size( &ctx->P  );
+    n2 = mpi_size( &ctx->G  );
+    n3 = mpi_size( &ctx->GX );
+
+    p = output;
+    DHM_MPI_EXPORT( &ctx->P , n1 );
+    DHM_MPI_EXPORT( &ctx->G , n2 );
+    DHM_MPI_EXPORT( &ctx->GX, n3 );
+
+    *olen  = p - output;
+
+    ctx->len = n1;
+
+cleanup:
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Import the peer's public value G^Y
+ */
+int dhm_read_public( dhm_context *ctx,
+                     const unsigned char *input, size_t ilen )
+{
+    int ret;
+
+    if( ctx == NULL || ilen < 1 || ilen > ctx->len )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
+        return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Create own private value X and export G^X
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t olen,
+                     int (*f_rng)(void *), void *p_rng )
+{
+    int ret, n;
+
+    if( ctx == NULL || olen < 1 || olen > ctx->len )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    /*
+     * generate X and calculate GX = G^X mod P
+     */
+    n = x_size / sizeof( t_uint ) + 1;
+
+    mpi_fill_random( &ctx->X, n, f_rng, p_rng );
+
+    while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+           mpi_shift_r( &ctx->X, 1 );
+
+    MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+                          &ctx->P , &ctx->RP ) );
+
+    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+        return( ret );
+
+    MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
+
+cleanup:
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Derive and export the shared secret (G^Y)^X mod P
+ */
+int dhm_calc_secret( dhm_context *ctx,
+                     unsigned char *output, size_t *olen )
+{
+    int ret;
+
+    if( ctx == NULL || *olen < ctx->len )
+        return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+    MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
+                          &ctx->P, &ctx->RP ) );
+
+    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+        return( ret );
+
+    *olen = mpi_size( &ctx->K );
+
+    MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
+
+cleanup:
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx )
+{
+    mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
+    mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
+    mpi_free( &ctx->P );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int dhm_self_test( int verbose )
+{
+    return( verbose++ );
+}
+
+#endif
+
+#endif

+ 418 - 0
thirdparty/PolarSSL/library/error.c

@@ -0,0 +1,418 @@
+/*
+ *  Error message information
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_ERROR_C)
+
+#if defined(POLARSSL_AES_C)
+#include "polarssl/aes.h"
+#endif
+
+#if defined(POLARSSL_BASE64_C)
+#include "polarssl/base64.h"
+#endif
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+#include "polarssl/camellia.h"
+#endif
+
+#if defined(POLARSSL_CIPHER_C)
+#include "polarssl/cipher.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+#if defined(POLARSSL_DHM_C)
+#include "polarssl/dhm.h"
+#endif
+
+#if defined(POLARSSL_MD_C)
+#include "polarssl/md.h"
+#endif
+
+#if defined(POLARSSL_NET_C)
+#include "polarssl/net.h"
+#endif
+
+#if defined(POLARSSL_PADLOCK_C)
+#include "polarssl/padlock.h"
+#endif
+
+#if defined(POLARSSL_PEM_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C)
+#include "polarssl/ssl.h"
+#endif
+
+#if defined(POLARSSL_X509_PARSE_C)
+#include "polarssl/x509.h"
+#endif
+
+#if defined(POLARSSL_XTEA_C)
+#include "polarssl/xtea.h"
+#endif
+
+
+#include <string.h>
+
+void error_strerror( int ret, char *buf, size_t buflen )
+{
+    size_t len;
+    int use_ret;
+
+    memset( buf, 0x00, buflen );
+     
+    if( ret < 0 )
+        ret = -ret;
+
+    if( ret & 0xFF80 )
+    {
+        use_ret = ret & 0xFF80;
+
+        // High level error codes
+        //
+#if defined(POLARSSL_CIPHER_C)
+        if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "CIPHER - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) )
+            snprintf( buf, buflen, "CIPHER - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) )
+            snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" );
+        if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) )
+            snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" );
+#endif /* POLARSSL_CIPHER_C */
+
+#if defined(POLARSSL_DHM_C)
+        if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "DHM - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) )
+            snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) )
+            snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) )
+            snprintf( buf, buflen, "DHM - Reading of the public values failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) )
+            snprintf( buf, buflen, "DHM - Makeing of the public value failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
+            snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_MD_C)
+        if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "MD - The selected feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "MD - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) )
+            snprintf( buf, buflen, "MD - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_MD_FILE_OPEN_FAILED) )
+            snprintf( buf, buflen, "MD - Opening of file failed" );
+        if( use_ret == -(POLARSSL_ERR_MD_FILE_READ_FAILED) )
+            snprintf( buf, buflen, "MD - Failure when reading from file" );
+#endif /* POLARSSL_MD_C */
+
+#if defined(POLARSSL_PEM_C)
+        if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_PRESENT) )
+            snprintf( buf, buflen, "PEM - No PEM header found" );
+        if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) )
+            snprintf( buf, buflen, "PEM - PEM string is not as expected" );
+        if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) )
+            snprintf( buf, buflen, "PEM - Failed to allocate memory" );
+        if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) )
+            snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" );
+        if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) )
+            snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" );
+        if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) )
+            snprintf( buf, buflen, "PEM - Private key password can't be empty" );
+        if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) )
+            snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" );
+        if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" );
+#endif /* POLARSSL_PEM_C */
+
+#if defined(POLARSSL_RSA_C)
+        if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "RSA - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) )
+            snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" );
+        if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) )
+            snprintf( buf, buflen, "RSA - Something failed during generation of a key" );
+        if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) )
+            snprintf( buf, buflen, "RSA - Key failed to pass the libraries validity check" );
+        if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) )
+            snprintf( buf, buflen, "RSA - The public key operation failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) )
+            snprintf( buf, buflen, "RSA - The private key operation failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) )
+            snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" );
+        if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) )
+            snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
+        if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) )
+            snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_SSL_TLS_C)
+        if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "SSL - The requested feature is not available" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) )
+            snprintf( buf, buflen, "SSL - Bad input parameters to function" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) )
+            snprintf( buf, buflen, "SSL - Verification of the message MAC failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) )
+            snprintf( buf, buflen, "SSL - An invalid SSL record was received" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) )
+            snprintf( buf, buflen, "SSL - The connection indicated an EOF" );
+        if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) )
+            snprintf( buf, buflen, "SSL - An unknown cipher was received" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) )
+            snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_SESSION_FOUND) )
+            snprintf( buf, buflen, "SSL - No session to recover was found" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) )
+            snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) )
+            snprintf( buf, buflen, "SSL - DESCRIPTION MISSING" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) )
+            snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) )
+            snprintf( buf, buflen, "SSL - The own private key is not set, but needed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) )
+            snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" );
+        if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) )
+            snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" );
+        if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) )
+            snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) )
+            snprintf( buf, buflen, "SSL - Verification of our peer failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) )
+            snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) )
+            snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) )
+            snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) )
+            snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) )
+            snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) )
+            snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Read Public" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS) )
+            snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) )
+            snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) )
+            snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" );
+        if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) )
+            snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" );
+#endif /* POLARSSL_SSL_TLS_C */
+
+#if defined(POLARSSL_X509_PARSE_C)
+        if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) )
+            snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PEM) )
+            snprintf( buf, buflen, "X509 - The PEM-encoded certificate contains invalid elements, e.g. invalid character" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_FORMAT) )
+            snprintf( buf, buflen, "X509 - The certificate format is invalid, e.g. different type expected" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_VERSION) )
+            snprintf( buf, buflen, "X509 - The certificate version element is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SERIAL) )
+            snprintf( buf, buflen, "X509 - The serial tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_ALG) )
+            snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_NAME) )
+            snprintf( buf, buflen, "X509 - The name tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_DATE) )
+            snprintf( buf, buflen, "X509 - The date tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PUBKEY) )
+            snprintf( buf, buflen, "X509 - The pubkey tag or value is invalid (only RSA is supported)" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE) )
+            snprintf( buf, buflen, "X509 - The signature tag or value invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS) )
+            snprintf( buf, buflen, "X509 - The extension tag or value is invalid" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION) )
+            snprintf( buf, buflen, "X509 - Certificate or CRL has an unsupported version number" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG) )
+            snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" );
+        if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_PK_ALG) )
+            snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA is supported)" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_SIG_MISMATCH) )
+            snprintf( buf, buflen, "X509 - Certificate signature algorithms do not match. (see \\c ::x509_cert sig_oid)" );
+        if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) )
+            snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
+        if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_VERSION) )
+            snprintf( buf, buflen, "X509 - Unsupported RSA key version" );
+        if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_FORMAT) )
+            snprintf( buf, buflen, "X509 - Invalid RSA key tag or value" );
+        if( use_ret == -(POLARSSL_ERR_X509_POINT_ERROR) )
+            snprintf( buf, buflen, "X509 - Not used" );
+        if( use_ret == -(POLARSSL_ERR_X509_VALUE_TO_LENGTH) )
+            snprintf( buf, buflen, "X509 - Not used" );
+#endif /* POLARSSL_X509_PARSE_C */
+
+        if( strlen( buf ) == 0 )
+            snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+    }
+
+    use_ret = ret & ~0xFF80;
+
+    if( use_ret == 0 )
+        return;
+
+    // If high level code is present, make a concatenation between both
+    // error strings.
+    //
+    len = strlen( buf );
+
+    if( len > 0 )
+    {
+        if( buflen - len < 5 )
+            return;
+
+        snprintf( buf + len, buflen - len, " : " );
+
+        buf += len + 3;
+        buflen -= len + 3;
+    }
+
+    // Low level error codes
+    //
+#if defined(POLARSSL_AES_C)
+    if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) )
+        snprintf( buf, buflen, "AES - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "AES - Invalid data input length" );
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_BASE64_C)
+    if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) )
+        snprintf( buf, buflen, "BASE64 - Output buffer too small" );
+    if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) )
+        snprintf( buf, buflen, "BASE64 - Invalid character in input" );
+#endif /* POLARSSL_BASE64_C */
+
+#if defined(POLARSSL_BIGNUM_C)
+    if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" );
+    if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) )
+        snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" );
+    if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) )
+        snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" );
+    if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) )
+        snprintf( buf, buflen, "BIGNUM - The output buffer is too small to write too" );
+    if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) )
+        snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" );
+    if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) )
+        snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" );
+    if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) )
+        snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" );
+#endif /* POLARSSL_BIGNUM_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+    if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) )
+        snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
+    if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+    if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "DES - The data input has an invalid length" );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_NET_C)
+    if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) )
+        snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" );
+    if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) )
+        snprintf( buf, buflen, "NET - Failed to open a socket" );
+    if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) )
+        snprintf( buf, buflen, "NET - The connection to the given server / port failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) )
+        snprintf( buf, buflen, "NET - Binding of the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) )
+        snprintf( buf, buflen, "NET - Could not listen on the socket" );
+    if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) )
+        snprintf( buf, buflen, "NET - Could not accept the incoming connection" );
+    if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) )
+        snprintf( buf, buflen, "NET - Reading information from the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) )
+        snprintf( buf, buflen, "NET - Sending information through the socket failed" );
+    if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) )
+        snprintf( buf, buflen, "NET - Connection was reset by peer" );
+    if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) )
+        snprintf( buf, buflen, "NET - Connection requires a read call" );
+    if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) )
+        snprintf( buf, buflen, "NET - Connection requires a write call" );
+#endif /* POLARSSL_NET_C */
+
+#if defined(POLARSSL_PADLOCK_C)
+    if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) )
+        snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
+#endif /* POLARSSL_PADLOCK_C */
+
+#if defined(POLARSSL_X509_PARSE_C)
+    if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) )
+        snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) )
+        snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) )
+        snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) )
+        snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
+    if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) )
+        snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
+#endif /* POLARSSL_X509_PARSE_C */
+
+#if defined(POLARSSL_XTEA_C)
+    if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) )
+        snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
+#endif /* POLARSSL_XTEA_C */
+
+    if( strlen( buf ) != 0 )
+        return;
+
+    snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+}
+
+#endif /* POLARSSL_VERBOSE_ERROR */

+ 217 - 0
thirdparty/PolarSSL/library/havege.c

@@ -0,0 +1,217 @@
+/**
+ *  \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The HAVEGE RNG was designed by Andre Seznec in 2002.
+ *
+ *  http://www.irisa.fr/caps/projects/hipsor/publi.php
+ *
+ *  Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_HAVEGE_C)
+
+#include "polarssl/havege.h"
+#include "polarssl/timing.h"
+
+#include <string.h>
+#include <time.h>
+
+/* ------------------------------------------------------------------------
+ * On average, one iteration accesses two 8-word blocks in the havege WALK
+ * table, and generates 16 words in the RES array.
+ *
+ * The data read in the WALK table is updated and permuted after each use.
+ * The result of the hardware clock counter read is used  for this update.
+ *
+ * 25 conditional tests are present.  The conditional tests are grouped in
+ * two nested  groups of 12 conditional tests and 1 test that controls the
+ * permutation; on average, there should be 6 tests executed and 3 of them
+ * should be mispredicted.
+ * ------------------------------------------------------------------------
+ */
+
+#define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
+
+#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+
+#define TST1_LEAVE U1++; }
+#define TST2_LEAVE U2++; }
+
+#define ONE_ITERATION                                   \
+                                                        \
+    PTEST = PT1 >> 20;                                  \
+                                                        \
+    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
+    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
+    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
+                                                        \
+    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
+    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
+    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
+                                                        \
+    PTX = (PT1 >> 18) & 7;                              \
+    PT1 &= 0x1FFF;                                      \
+    PT2 &= 0x1FFF;                                      \
+    CLK = (int) hardclock();                            \
+                                                        \
+    i = 0;                                              \
+    A = &WALK[PT1    ]; RES[i++] ^= *A;                 \
+    B = &WALK[PT2    ]; RES[i++] ^= *B;                 \
+    C = &WALK[PT1 ^ 1]; RES[i++] ^= *C;                 \
+    D = &WALK[PT2 ^ 4]; RES[i++] ^= *D;                 \
+                                                        \
+    IN = (*A >> (1)) ^ (*A << (31)) ^ CLK;              \
+    *A = (*B >> (2)) ^ (*B << (30)) ^ CLK;              \
+    *B = IN ^ U1;                                       \
+    *C = (*C >> (3)) ^ (*C << (29)) ^ CLK;              \
+    *D = (*D >> (4)) ^ (*D << (28)) ^ CLK;              \
+                                                        \
+    A = &WALK[PT1 ^ 2]; RES[i++] ^= *A;                 \
+    B = &WALK[PT2 ^ 2]; RES[i++] ^= *B;                 \
+    C = &WALK[PT1 ^ 3]; RES[i++] ^= *C;                 \
+    D = &WALK[PT2 ^ 6]; RES[i++] ^= *D;                 \
+                                                        \
+    if( PTEST & 1 ) SWAP( A, C );                       \
+                                                        \
+    IN = (*A >> (5)) ^ (*A << (27)) ^ CLK;              \
+    *A = (*B >> (6)) ^ (*B << (26)) ^ CLK;              \
+    *B = IN; CLK = (int) hardclock();                   \
+    *C = (*C >> (7)) ^ (*C << (25)) ^ CLK;              \
+    *D = (*D >> (8)) ^ (*D << (24)) ^ CLK;              \
+                                                        \
+    A = &WALK[PT1 ^ 4];                                 \
+    B = &WALK[PT2 ^ 1];                                 \
+                                                        \
+    PTEST = PT2 >> 1;                                   \
+                                                        \
+    PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]);   \
+    PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8);  \
+    PTY = (PT2 >> 10) & 7;                              \
+                                                        \
+    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
+    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
+    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
+                                                        \
+    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
+    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
+    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
+                                                        \
+    C = &WALK[PT1 ^ 5];                                 \
+    D = &WALK[PT2 ^ 5];                                 \
+                                                        \
+    RES[i++] ^= *A;                                     \
+    RES[i++] ^= *B;                                     \
+    RES[i++] ^= *C;                                     \
+    RES[i++] ^= *D;                                     \
+                                                        \
+    IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK;             \
+    *A = (*B >> (10)) ^ (*B << (22)) ^ CLK;             \
+    *B = IN ^ U2;                                       \
+    *C = (*C >> (11)) ^ (*C << (21)) ^ CLK;             \
+    *D = (*D >> (12)) ^ (*D << (20)) ^ CLK;             \
+                                                        \
+    A = &WALK[PT1 ^ 6]; RES[i++] ^= *A;                 \
+    B = &WALK[PT2 ^ 3]; RES[i++] ^= *B;                 \
+    C = &WALK[PT1 ^ 7]; RES[i++] ^= *C;                 \
+    D = &WALK[PT2 ^ 7]; RES[i++] ^= *D;                 \
+                                                        \
+    IN = (*A >> (13)) ^ (*A << (19)) ^ CLK;             \
+    *A = (*B >> (14)) ^ (*B << (18)) ^ CLK;             \
+    *B = IN;                                            \
+    *C = (*C >> (15)) ^ (*C << (17)) ^ CLK;             \
+    *D = (*D >> (16)) ^ (*D << (16)) ^ CLK;             \
+                                                        \
+    PT1 = ( RES[(i - 8) ^ PTX] ^                        \
+            WALK[PT1 ^ PTX ^ 7] ) & (~1);               \
+    PT1 ^= (PT2 ^ 0x10) & 0x10;                         \
+                                                        \
+    for( n++, i = 0; i < 16; i++ )                      \
+        hs->pool[n % COLLECT_SIZE] ^= RES[i];
+
+/*
+ * Entropy gathering function
+ */
+static void havege_fill( havege_state *hs )
+{
+    int i, n = 0;
+    int  U1,  U2, *A, *B, *C, *D;
+    int PT1, PT2, *WALK, RES[16];
+    int PTX, PTY, CLK, PTEST, IN;
+
+    WALK = hs->WALK;
+    PT1  = hs->PT1;
+    PT2  = hs->PT2;
+
+    PTX  = U1 = 0;
+    PTY  = U2 = 0;
+
+    memset( RES, 0, sizeof( RES ) );
+
+    while( n < COLLECT_SIZE * 4 )
+    {
+        ONE_ITERATION
+        ONE_ITERATION
+        ONE_ITERATION
+        ONE_ITERATION
+    }
+
+    hs->PT1 = PT1;
+    hs->PT2 = PT2;
+
+    hs->offset[0] = 0;
+    hs->offset[1] = COLLECT_SIZE / 2;
+}
+
+/*
+ * HAVEGE initialization
+ */
+void havege_init( havege_state *hs )
+{
+    memset( hs, 0, sizeof( havege_state ) );
+
+    havege_fill( hs );
+}
+
+/*
+ * HAVEGE rand function
+ */
+int havege_rand( void *p_rng )
+{
+    int ret;
+    havege_state *hs = (havege_state *) p_rng;
+
+    if( hs->offset[1] >= COLLECT_SIZE )
+        havege_fill( hs );
+
+    ret  = hs->pool[hs->offset[0]++];
+    ret ^= hs->pool[hs->offset[1]++];
+
+    return( ret );
+}
+
+#endif

+ 302 - 0
thirdparty/PolarSSL/library/md.c

@@ -0,0 +1,302 @@
+/**
+ * \file md.c
+ * 
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md.h"
+#include "polarssl/md_wrap.h"
+
+#include <stdlib.h>
+#include <stdlib.h>
+#if defined ( __GNUC__ )
+#include <my_strings.h>
+#endif
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+static const int supported_digests[] = {
+
+#if defined(POLARSSL_MD2_C)
+        POLARSSL_MD_MD2,
+#endif
+
+#if defined(POLARSSL_MD4_C)
+        POLARSSL_MD_MD4,
+#endif
+
+#if defined(POLARSSL_MD5_C)
+        POLARSSL_MD_MD5,
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+        POLARSSL_MD_SHA1,
+#endif
+
+#if defined(POLARSSL_SHA2_C)
+        POLARSSL_MD_SHA224,
+        POLARSSL_MD_SHA256,
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+        POLARSSL_MD_SHA384,
+        POLARSSL_MD_SHA512,
+#endif
+
+        0
+};
+
+const int *md_list( void )
+{
+    return supported_digests;
+}
+
+const md_info_t *md_info_from_string( const char *md_name )
+{
+    if( NULL == md_name )
+        return NULL;
+
+    /* Get the appropriate digest information */
+#if defined(POLARSSL_MD2_C)
+    if( !strcasecmp( "MD2", md_name ) )
+        return md_info_from_type( POLARSSL_MD_MD2 );
+#endif
+#if defined(POLARSSL_MD4_C)
+    if( !strcasecmp( "MD4", md_name ) )
+        return md_info_from_type( POLARSSL_MD_MD4 );
+#endif
+#if defined(POLARSSL_MD5_C)
+    if( !strcasecmp( "MD5", md_name ) )
+        return md_info_from_type( POLARSSL_MD_MD5 );
+#endif
+#if defined(POLARSSL_SHA1_C)
+    if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA1 );
+#endif
+#if defined(POLARSSL_SHA2_C)
+    if( !strcasecmp( "SHA224", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA224 );
+    if( !strcasecmp( "SHA256", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA256 );
+#endif
+#if defined(POLARSSL_SHA4_C)
+    if( !strcasecmp( "SHA384", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA384 );
+    if( !strcasecmp( "SHA512", md_name ) )
+        return md_info_from_type( POLARSSL_MD_SHA512 );
+#endif
+    return NULL;
+}
+
+const md_info_t *md_info_from_type( md_type_t md_type )
+{
+    switch( md_type )
+    {
+#if defined(POLARSSL_MD2_C)
+        case POLARSSL_MD_MD2:
+            return &md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+        case POLARSSL_MD_MD4:
+            return &md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+        case POLARSSL_MD_MD5:
+            return &md5_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+        case POLARSSL_MD_SHA1:
+            return &sha1_info;
+#endif
+#if defined(POLARSSL_SHA2_C)
+        case POLARSSL_MD_SHA224:
+            return &sha224_info;
+        case POLARSSL_MD_SHA256:
+            return &sha256_info;
+#endif
+#if defined(POLARSSL_SHA4_C)
+        case POLARSSL_MD_SHA384:
+            return &sha384_info;
+        case POLARSSL_MD_SHA512:
+            return &sha512_info;
+#endif
+        default:
+            return NULL;
+    }
+}
+
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info )
+{
+    if( md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    if( ctx == NULL || ctx->md_ctx != NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
+        return POLARSSL_ERR_MD_ALLOC_FAILED;
+
+    ctx->md_info = md_info;
+
+    md_info->starts_func( ctx->md_ctx );
+
+    return 0;
+}
+
+int md_free_ctx( md_context_t *ctx )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->ctx_free_func( ctx->md_ctx );
+    ctx->md_ctx = NULL;
+
+    return 0;
+}
+
+int md_starts( md_context_t *ctx )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->starts_func( ctx->md_ctx );
+
+    return 0;
+}
+
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->update_func( ctx->md_ctx, input, ilen );
+
+    return 0;
+}
+
+int md_finish( md_context_t *ctx, unsigned char *output )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->finish_func( ctx->md_ctx, output );
+
+    return 0;
+}
+
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+            unsigned char *output )
+{
+    if ( md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    md_info->digest_func( input, ilen, output );
+
+    return 0;
+}
+
+int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
+{
+    int ret;
+
+    if( md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_FS_IO)
+    ret = md_info->file_func( path, output );
+    if( ret == 2 )
+        return POLARSSL_ERR_MD_FILE_OPEN_FAILED;
+    if( ret == 3 )
+        return POLARSSL_ERR_MD_FILE_READ_FAILED;
+
+    return ret;
+#else
+    ((void) path);
+    ((void) output);
+
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen);
+
+    return 0;
+}
+
+int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen );
+
+    return 0;
+}
+
+int md_hmac_finish( md_context_t *ctx, unsigned char *output)
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_finish_func( ctx->md_ctx, output);
+
+    return 0;
+}
+
+int md_hmac_reset( md_context_t *ctx )
+{
+    if( ctx == NULL || ctx->md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    ctx->md_info->hmac_reset_func( ctx->md_ctx);
+
+    return 0;
+}
+
+int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char *output )
+{
+    if( md_info == NULL )
+        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+    md_info->hmac_func( key, keylen, input, ilen, output );
+
+    return 0;
+}
+
+#endif

+ 369 - 0
thirdparty/PolarSSL/library/md2.c

@@ -0,0 +1,369 @@
+/*
+ *  RFC 1115/1319 compliant MD2 implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The MD2 algorithm was designed by Ron Rivest in 1989.
+ *
+ *  http://www.ietf.org/rfc/rfc1115.txt
+ *  http://www.ietf.org/rfc/rfc1319.txt
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_MD2_C)
+
+#include "polarssl/md2.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#endif
+
+static const unsigned char PI_SUBST[256] =
+{
+    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
+    0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
+    0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
+    0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+    0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
+    0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
+    0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
+    0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
+    0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
+    0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
+    0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+    0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
+    0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
+    0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
+    0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
+    0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
+    0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
+    0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+    0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
+    0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
+    0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
+    0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
+    0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
+};
+
+/*
+ * MD2 context setup
+ */
+void md2_starts( md2_context *ctx )
+{
+    memset( ctx->cksum, 0, 16 );
+    memset( ctx->state, 0, 46 );
+    memset( ctx->buffer, 0, 16 );
+    ctx->left = 0;
+}
+
+static void md2_process( md2_context *ctx )
+{
+    int i, j;
+    unsigned char t = 0;
+
+    for( i = 0; i < 16; i++ )
+    {
+        ctx->state[i + 16] = ctx->buffer[i];
+        ctx->state[i + 32] =
+            (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
+    }
+
+    for( i = 0; i < 18; i++ )
+    {
+        for( j = 0; j < 48; j++ )
+        {
+            ctx->state[j] = (unsigned char)
+               ( ctx->state[j] ^ PI_SUBST[t] );
+            t  = ctx->state[j];
+        }
+
+        t = (unsigned char)( t + i );
+    }
+
+    t = ctx->cksum[15];
+
+    for( i = 0; i < 16; i++ )
+    {
+        ctx->cksum[i] = (unsigned char)
+           ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
+        t  = ctx->cksum[i];
+    }
+}
+
+/*
+ * MD2 process buffer
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+
+    while( ilen > 0 )
+    {
+        if( ctx->left + ilen > 16 )
+            fill = 16 - ctx->left;
+        else
+            fill = ilen;
+
+        memcpy( ctx->buffer + ctx->left, input, fill );
+
+        ctx->left += fill;
+        input += fill;
+        ilen  -= fill;
+
+        if( ctx->left == 16 )
+        {
+            ctx->left = 0;
+            md2_process( ctx );
+        }
+    }
+}
+
+/*
+ * MD2 final digest
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] )
+{
+    size_t i;
+    unsigned char x;
+
+    x = (unsigned char)( 16 - ctx->left );
+
+    for( i = ctx->left; i < 16; i++ )
+        ctx->buffer[i] = x;
+
+    md2_process( ctx );
+
+    memcpy( ctx->buffer, ctx->cksum, 16 );
+    md2_process( ctx );
+
+    memcpy( output, ctx->state, 16 );
+}
+
+/*
+ * output = MD2( input buffer )
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+    md2_context ctx;
+
+    md2_starts( &ctx );
+    md2_update( &ctx, input, ilen );
+    md2_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD2( file contents )
+ */
+int md2_file( const char *path, unsigned char output[16] )
+{
+    FILE *f;
+    size_t n;
+    md2_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( 1 );
+
+    md2_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md2_update( &ctx, buf, n );
+
+    md2_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md2_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( 2 );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD2 HMAC context setup
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen )
+{
+    size_t i;
+    unsigned char sum[16];
+
+    if( keylen > 64 )
+    {
+        md2( key, keylen, sum );
+        keylen = 16;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    md2_starts( ctx );
+    md2_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD2 HMAC process buffer
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+{
+    md2_update( ctx, input, ilen );
+}
+
+/*
+ * MD2 HMAC final digest
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] )
+{
+    unsigned char tmpbuf[16];
+
+    md2_finish( ctx, tmpbuf );
+    md2_starts( ctx );
+    md2_update( ctx, ctx->opad, 64 );
+    md2_update( ctx, tmpbuf, 16 );
+    md2_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD2 HMAC context reset
+ */
+void md2_hmac_reset( md2_context *ctx )
+{
+    md2_starts( ctx );
+    md2_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD2( hmac key, input buffer )
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] )
+{
+    md2_context ctx;
+
+    md2_hmac_starts( &ctx, key, keylen );
+    md2_hmac_update( &ctx, input, ilen );
+    md2_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1319 test vectors
+ */
+static const char md2_test_str[7][81] =
+{
+    { "" },
+    { "a" },
+    { "abc" },
+    { "message digest" },
+    { "abcdefghijklmnopqrstuvwxyz" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+    { "12345678901234567890123456789012345678901234567890123456789012" \
+      "345678901234567890" }
+};
+
+static const unsigned char md2_test_sum[7][16] =
+{
+    { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
+      0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
+    { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
+      0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
+    { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
+      0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
+    { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
+      0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
+    { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
+      0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
+    { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
+      0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
+    { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
+      0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
+};
+
+/*
+ * Checkup routine
+ */
+int md2_self_test( int verbose )
+{
+    int i;
+    unsigned char md2sum[16];
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            printf( "  MD2 test #%d: ", i + 1 );
+
+        md2( (unsigned char *) md2_test_str[i],
+             strlen( md2_test_str[i] ), md2sum );
+
+        if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 465 - 0
thirdparty/PolarSSL/library/md4.c

@@ -0,0 +1,465 @@
+/*
+ *  RFC 1186/1320 compliant MD4 implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The MD4 algorithm was designed by Ron Rivest in 1990.
+ *
+ *  http://www.ietf.org/rfc/rfc1186.txt
+ *  http://www.ietf.org/rfc/rfc1320.txt
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_MD4_C)
+
+#include "polarssl/md4.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#endif
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_ULONG_LE
+#define GET_ULONG_LE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ]       )        \
+        | ( (unsigned long) (b)[(i) + 1] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 2] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 3] << 24 );       \
+}
+#endif
+
+#ifndef PUT_ULONG_LE
+#define PUT_ULONG_LE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+/*
+ * MD4 context setup
+ */
+void md4_starts( md4_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}
+
+static void md4_process( md4_context *ctx, const unsigned char data[64] )
+{
+    unsigned long X[16], A, B, C, D;
+
+    GET_ULONG_LE( X[ 0], data,  0 );
+    GET_ULONG_LE( X[ 1], data,  4 );
+    GET_ULONG_LE( X[ 2], data,  8 );
+    GET_ULONG_LE( X[ 3], data, 12 );
+    GET_ULONG_LE( X[ 4], data, 16 );
+    GET_ULONG_LE( X[ 5], data, 20 );
+    GET_ULONG_LE( X[ 6], data, 24 );
+    GET_ULONG_LE( X[ 7], data, 28 );
+    GET_ULONG_LE( X[ 8], data, 32 );
+    GET_ULONG_LE( X[ 9], data, 36 );
+    GET_ULONG_LE( X[10], data, 40 );
+    GET_ULONG_LE( X[11], data, 44 );
+    GET_ULONG_LE( X[12], data, 48 );
+    GET_ULONG_LE( X[13], data, 52 );
+    GET_ULONG_LE( X[14], data, 56 );
+    GET_ULONG_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+
+#define F(x, y, z) ((x & y) | ((~x) & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
+
+    P( A, B, C, D, X[ 0],  3 );
+    P( D, A, B, C, X[ 1],  7 );
+    P( C, D, A, B, X[ 2], 11 );
+    P( B, C, D, A, X[ 3], 19 );
+    P( A, B, C, D, X[ 4],  3 );
+    P( D, A, B, C, X[ 5],  7 );
+    P( C, D, A, B, X[ 6], 11 );
+    P( B, C, D, A, X[ 7], 19 );
+    P( A, B, C, D, X[ 8],  3 );
+    P( D, A, B, C, X[ 9],  7 );
+    P( C, D, A, B, X[10], 11 );
+    P( B, C, D, A, X[11], 19 );
+    P( A, B, C, D, X[12],  3 );
+    P( D, A, B, C, X[13],  7 );
+    P( C, D, A, B, X[14], 11 );
+    P( B, C, D, A, X[15], 19 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) ((x & y) | (x & z) | (y & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
+
+    P( A, B, C, D, X[ 0],  3 );
+    P( D, A, B, C, X[ 4],  5 );
+    P( C, D, A, B, X[ 8],  9 );
+    P( B, C, D, A, X[12], 13 );
+    P( A, B, C, D, X[ 1],  3 );
+    P( D, A, B, C, X[ 5],  5 );
+    P( C, D, A, B, X[ 9],  9 );
+    P( B, C, D, A, X[13], 13 );
+    P( A, B, C, D, X[ 2],  3 );
+    P( D, A, B, C, X[ 6],  5 );
+    P( C, D, A, B, X[10],  9 );
+    P( B, C, D, A, X[14], 13 );
+    P( A, B, C, D, X[ 3],  3 );
+    P( D, A, B, C, X[ 7],  5 );
+    P( C, D, A, B, X[11],  9 );
+    P( B, C, D, A, X[15], 13 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
+
+    P( A, B, C, D, X[ 0],  3 );
+    P( D, A, B, C, X[ 8],  9 );
+    P( C, D, A, B, X[ 4], 11 );
+    P( B, C, D, A, X[12], 15 );
+    P( A, B, C, D, X[ 2],  3 );
+    P( D, A, B, C, X[10],  9 );
+    P( C, D, A, B, X[ 6], 11 );
+    P( B, C, D, A, X[14], 15 );
+    P( A, B, C, D, X[ 1],  3 );
+    P( D, A, B, C, X[ 9],  9 );
+    P( C, D, A, B, X[ 5], 11 );
+    P( B, C, D, A, X[13], 15 );
+    P( A, B, C, D, X[ 3],  3 );
+    P( D, A, B, C, X[11],  9 );
+    P( C, D, A, B, X[ 7], 11 );
+    P( B, C, D, A, X[15], 15 );
+
+#undef F
+#undef P
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+}
+
+/*
+ * MD4 process buffer
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    unsigned long left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (unsigned long) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (unsigned long) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        md4_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        md4_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, ilen );
+    }
+}
+
+static const unsigned char md4_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD4 final digest
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] )
+{
+    unsigned long last, padn;
+    unsigned long high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_ULONG_LE( low,  msglen, 0 );
+    PUT_ULONG_LE( high, msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    md4_update( ctx, (unsigned char *) md4_padding, padn );
+    md4_update( ctx, msglen, 8 );
+
+    PUT_ULONG_LE( ctx->state[0], output,  0 );
+    PUT_ULONG_LE( ctx->state[1], output,  4 );
+    PUT_ULONG_LE( ctx->state[2], output,  8 );
+    PUT_ULONG_LE( ctx->state[3], output, 12 );
+}
+
+/*
+ * output = MD4( input buffer )
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+    md4_context ctx;
+
+    md4_starts( &ctx );
+    md4_update( &ctx, input, ilen );
+    md4_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD4( file contents )
+ */
+int md4_file( const char *path, unsigned char output[16] )
+{
+    FILE *f;
+    size_t n;
+    md4_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( 1 );
+
+    md4_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md4_update( &ctx, buf, n );
+
+    md4_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md4_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( 2 );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD4 HMAC context setup
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen )
+{
+    size_t i;
+    unsigned char sum[16];
+
+    if( keylen > 64 )
+    {
+        md4( key, keylen, sum );
+        keylen = 16;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    md4_starts( ctx );
+    md4_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD4 HMAC process buffer
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+{
+    md4_update( ctx, input, ilen );
+}
+
+/*
+ * MD4 HMAC final digest
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
+{
+    unsigned char tmpbuf[16];
+
+    md4_finish( ctx, tmpbuf );
+    md4_starts( ctx );
+    md4_update( ctx, ctx->opad, 64 );
+    md4_update( ctx, tmpbuf, 16 );
+    md4_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD4 HMAC context reset
+ */
+void md4_hmac_reset( md4_context *ctx )
+{
+    md4_starts( ctx );
+    md4_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD4( hmac key, input buffer )
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] )
+{
+    md4_context ctx;
+
+    md4_hmac_starts( &ctx, key, keylen );
+    md4_hmac_update( &ctx, input, ilen );
+    md4_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1320 test vectors
+ */
+static const char md4_test_str[7][81] =
+{
+    { "" }, 
+    { "a" },
+    { "abc" },
+    { "message digest" },
+    { "abcdefghijklmnopqrstuvwxyz" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+    { "12345678901234567890123456789012345678901234567890123456789012" \
+      "345678901234567890" }
+};
+
+static const unsigned char md4_test_sum[7][16] =
+{
+    { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
+      0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
+    { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
+      0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
+    { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
+      0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
+    { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
+      0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
+    { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
+      0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
+    { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
+      0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
+    { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
+      0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
+};
+
+/*
+ * Checkup routine
+ */
+int md4_self_test( int verbose )
+{
+    int i;
+    unsigned char md4sum[16];
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            printf( "  MD4 test #%d: ", i + 1 );
+
+        md4( (unsigned char *) md4_test_str[i],
+             strlen( md4_test_str[i] ), md4sum );
+
+        if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 685 - 0
thirdparty/PolarSSL/library/md5.c

@@ -0,0 +1,685 @@
+/*
+ *  RFC 1321 compliant MD5 implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The MD5 algorithm was designed by Ron Rivest in 1991.
+ *
+ *  http://www.ietf.org/rfc/rfc1321.txt
+ */
+
+/* Note: This file has been modified by ST's MCD Application Team, to support 
+   the hardware crypto engine embedded in STM32F417xx */
+
+#include "config.h"
+
+#if defined(POLARSSL_MD5_C)
+#include "main.h"
+#include "polarssl/md5.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#endif
+
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */ 
+HASH_InitTypeDef MD5_HASH_InitStructure;
+HASH_MsgDigest MD5_MessageDigest;
+#endif /* USE_STM32F4XX_HW_CRYPTO */ 
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_ULONG_LE
+#define GET_ULONG_LE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ]       )        \
+        | ( (unsigned long) (b)[(i) + 1] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 2] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 3] << 24 );       \
+}
+#endif
+
+#ifndef PUT_ULONG_LE
+#define PUT_ULONG_LE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+/*
+ * MD5 context setup
+ */
+void md5_starts( md5_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}
+
+static void md5_process( md5_context *ctx, const unsigned char data[64] )
+{
+    unsigned long X[16], A, B, C, D;
+
+    GET_ULONG_LE( X[ 0], data,  0 );
+    GET_ULONG_LE( X[ 1], data,  4 );
+    GET_ULONG_LE( X[ 2], data,  8 );
+    GET_ULONG_LE( X[ 3], data, 12 );
+    GET_ULONG_LE( X[ 4], data, 16 );
+    GET_ULONG_LE( X[ 5], data, 20 );
+    GET_ULONG_LE( X[ 6], data, 24 );
+    GET_ULONG_LE( X[ 7], data, 28 );
+    GET_ULONG_LE( X[ 8], data, 32 );
+    GET_ULONG_LE( X[ 9], data, 36 );
+    GET_ULONG_LE( X[10], data, 40 );
+    GET_ULONG_LE( X[11], data, 44 );
+    GET_ULONG_LE( X[12], data, 48 );
+    GET_ULONG_LE( X[13], data, 52 );
+    GET_ULONG_LE( X[14], data, 56 );
+    GET_ULONG_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t)                                \
+{                                                       \
+    a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+    P( A, B, C, D,  0,  7, 0xD76AA478 );
+    P( D, A, B, C,  1, 12, 0xE8C7B756 );
+    P( C, D, A, B,  2, 17, 0x242070DB );
+    P( B, C, D, A,  3, 22, 0xC1BDCEEE );
+    P( A, B, C, D,  4,  7, 0xF57C0FAF );
+    P( D, A, B, C,  5, 12, 0x4787C62A );
+    P( C, D, A, B,  6, 17, 0xA8304613 );
+    P( B, C, D, A,  7, 22, 0xFD469501 );
+    P( A, B, C, D,  8,  7, 0x698098D8 );
+    P( D, A, B, C,  9, 12, 0x8B44F7AF );
+    P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
+    P( B, C, D, A, 11, 22, 0x895CD7BE );
+    P( A, B, C, D, 12,  7, 0x6B901122 );
+    P( D, A, B, C, 13, 12, 0xFD987193 );
+    P( C, D, A, B, 14, 17, 0xA679438E );
+    P( B, C, D, A, 15, 22, 0x49B40821 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+    P( A, B, C, D,  1,  5, 0xF61E2562 );
+    P( D, A, B, C,  6,  9, 0xC040B340 );
+    P( C, D, A, B, 11, 14, 0x265E5A51 );
+    P( B, C, D, A,  0, 20, 0xE9B6C7AA );
+    P( A, B, C, D,  5,  5, 0xD62F105D );
+    P( D, A, B, C, 10,  9, 0x02441453 );
+    P( C, D, A, B, 15, 14, 0xD8A1E681 );
+    P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
+    P( A, B, C, D,  9,  5, 0x21E1CDE6 );
+    P( D, A, B, C, 14,  9, 0xC33707D6 );
+    P( C, D, A, B,  3, 14, 0xF4D50D87 );
+    P( B, C, D, A,  8, 20, 0x455A14ED );
+    P( A, B, C, D, 13,  5, 0xA9E3E905 );
+    P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
+    P( C, D, A, B,  7, 14, 0x676F02D9 );
+    P( B, C, D, A, 12, 20, 0x8D2A4C8A );
+
+#undef F
+    
+#define F(x,y,z) (x ^ y ^ z)
+
+    P( A, B, C, D,  5,  4, 0xFFFA3942 );
+    P( D, A, B, C,  8, 11, 0x8771F681 );
+    P( C, D, A, B, 11, 16, 0x6D9D6122 );
+    P( B, C, D, A, 14, 23, 0xFDE5380C );
+    P( A, B, C, D,  1,  4, 0xA4BEEA44 );
+    P( D, A, B, C,  4, 11, 0x4BDECFA9 );
+    P( C, D, A, B,  7, 16, 0xF6BB4B60 );
+    P( B, C, D, A, 10, 23, 0xBEBFBC70 );
+    P( A, B, C, D, 13,  4, 0x289B7EC6 );
+    P( D, A, B, C,  0, 11, 0xEAA127FA );
+    P( C, D, A, B,  3, 16, 0xD4EF3085 );
+    P( B, C, D, A,  6, 23, 0x04881D05 );
+    P( A, B, C, D,  9,  4, 0xD9D4D039 );
+    P( D, A, B, C, 12, 11, 0xE6DB99E5 );
+    P( C, D, A, B, 15, 16, 0x1FA27CF8 );
+    P( B, C, D, A,  2, 23, 0xC4AC5665 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+    P( A, B, C, D,  0,  6, 0xF4292244 );
+    P( D, A, B, C,  7, 10, 0x432AFF97 );
+    P( C, D, A, B, 14, 15, 0xAB9423A7 );
+    P( B, C, D, A,  5, 21, 0xFC93A039 );
+    P( A, B, C, D, 12,  6, 0x655B59C3 );
+    P( D, A, B, C,  3, 10, 0x8F0CCC92 );
+    P( C, D, A, B, 10, 15, 0xFFEFF47D );
+    P( B, C, D, A,  1, 21, 0x85845DD1 );
+    P( A, B, C, D,  8,  6, 0x6FA87E4F );
+    P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
+    P( C, D, A, B,  6, 15, 0xA3014314 );
+    P( B, C, D, A, 13, 21, 0x4E0811A1 );
+    P( A, B, C, D,  4,  6, 0xF7537E82 );
+    P( D, A, B, C, 11, 10, 0xBD3AF235 );
+    P( C, D, A, B,  2, 15, 0x2AD7D2BB );
+    P( B, C, D, A,  9, 21, 0xEB86D391 );
+
+#undef F
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+}
+
+/*
+ * MD5 process buffer
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    unsigned long left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (unsigned long) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (unsigned long) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        md5_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        md5_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, ilen );
+    }
+}
+
+static const unsigned char md5_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD5 final digest
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] )
+{
+    unsigned long last, padn;
+    unsigned long high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_ULONG_LE( low,  msglen, 0 );
+    PUT_ULONG_LE( high, msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    md5_update( ctx, (unsigned char *) md5_padding, padn );
+    md5_update( ctx, msglen, 8 );
+
+    PUT_ULONG_LE( ctx->state[0], output,  0 );
+    PUT_ULONG_LE( ctx->state[1], output,  4 );
+    PUT_ULONG_LE( ctx->state[2], output,  8 );
+    PUT_ULONG_LE( ctx->state[3], output, 12 );
+}
+
+/*
+ * output = MD5( input buffer )
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+    md5_context ctx;
+
+    md5_starts( &ctx );
+    md5_update( &ctx, input, ilen );
+    md5_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md5_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD5( file contents )
+ */
+int md5_file( const char *path, unsigned char output[16] )
+{
+    FILE *f;
+    size_t n;
+    md5_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( 1 );
+
+    md5_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md5_update( &ctx, buf, n );
+
+    md5_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md5_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( 2 );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD5 HMAC context setup
+ */
+void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
+{
+    size_t i;
+    unsigned char sum[16];
+
+    if( keylen > 64 )
+    {
+        md5( key, keylen, sum );
+        keylen = 16;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    md5_starts( ctx );
+    md5_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD5 HMAC process buffer
+ */
+void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+{
+    md5_update( ctx, input, ilen );
+}
+
+/*
+ * MD5 HMAC final digest
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
+{
+    unsigned char tmpbuf[16];
+
+    md5_finish( ctx, tmpbuf );
+    md5_starts( ctx );
+    md5_update( ctx, ctx->opad, 64 );
+    md5_update( ctx, tmpbuf, 16 );
+    md5_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD5 HMAC context reset
+ */
+void md5_hmac_reset( md5_context *ctx )
+{
+    md5_starts( ctx );
+    md5_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD5( hmac key, input buffer )
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+               const unsigned char *input, size_t ilen,
+               unsigned char output[16] )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  __IO uint16_t nbvalidbitsdata = 0;
+  __IO uint16_t nbvalidbitskey = 0;
+  uint32_t i = 0;
+
+  /* Number of valid bits in last word of the input data */
+  nbvalidbitsdata = 8 * (ilen % 4);
+
+  /* Number of valid bits in last word of the Key */
+  nbvalidbitskey = 8 * (keylen % 4);
+   
+  /* HASH IP initialization */
+  HASH_DeInit();
+
+  /* HASH Configuration */
+  HASH_StructInit(&MD5_HASH_InitStructure);
+  MD5_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_MD5;
+  MD5_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
+  MD5_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+  if(keylen > 64)
+  {
+    /* HMAC long key */
+    MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey; 
+  }
+  else
+  {
+    /* HMAC short key */
+    MD5_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
+  }
+  HASH_Init(&MD5_HASH_InitStructure);
+   
+  /* Configure the number of valid bits in last word of the key */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+  /* Write the Key */
+  for(i = 0; i < keylen; i++)
+  {
+    HASH_DataIn(*(uint32_t*)&key[i]);
+    i = i + 3;
+  }
+  
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET);
+  
+  /* Configure the number of valid bits in last word of the input data */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+  /* Write the input block in the IN FIFO */
+  for(i = 0; i < ilen; i++)
+  {
+    HASH_DataIn(*(uint32_t*)&input[i]);
+    i = i + 3;
+  }
+
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET);  
+
+  /* Configure the number of valid bits in last word of the key */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+  /* Write the Key */
+  for(i = 0; i < keylen; i++)
+  {
+    HASH_DataIn(*(uint32_t*)&key[i]);
+    i = i + 3;
+  }
+  
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET);
+
+  /* Read the message digest */
+  HASH_GetDigest(&MD5_MessageDigest);
+  *(uint32_t*)&output[0] = __REV(MD5_MessageDigest.Data[0]);
+  *(uint32_t*)&output[4] = __REV(MD5_MessageDigest.Data[1]);
+  *(uint32_t*)&output[8] = __REV(MD5_MessageDigest.Data[2]);
+  *(uint32_t*)&output[12] = __REV(MD5_MessageDigest.Data[3]);
+
+#else /* use SW Crypto */
+
+    md5_context ctx;
+
+    md5_hmac_starts( &ctx, key, keylen );
+    md5_hmac_update( &ctx, input, ilen );
+    md5_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( md5_context ) );
+#endif /* USE_STM32F4XX_HW_CRYPTO */
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * RFC 1321 test vectors
+ */
+static unsigned char md5_test_buf[7][81] =
+{
+    { "" }, 
+    { "a" },
+    { "abc" },
+    { "message digest" },
+    { "abcdefghijklmnopqrstuvwxyz" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+    { "12345678901234567890123456789012345678901234567890123456789012" \
+      "345678901234567890" }
+};
+
+static const int md5_test_buflen[7] =
+{
+    0, 1, 3, 14, 26, 62, 80
+};
+
+static const unsigned char md5_test_sum[7][16] =
+{
+    { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
+      0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
+    { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
+      0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
+    { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
+      0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
+    { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
+      0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
+    { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
+      0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
+    { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
+      0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
+    { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
+      0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char md5_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 80 times */
+    { "" }
+};
+
+static const int md5_hmac_test_keylen[7] =
+{
+    16, 4, 16, 25, 16, 80, 80
+};
+
+static unsigned char md5_hmac_test_buf[7][74] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "Test Using Larger Than Block-Size Key and Larger"
+      " Than One Block-Size Data" }
+};
+
+static const int md5_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char md5_hmac_test_sum[7][16] =
+{
+    { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
+      0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
+    { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
+      0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
+    { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
+      0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
+    { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
+      0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
+    { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
+      0xF9, 0xBA, 0xB9, 0x95 },
+    { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
+      0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
+    { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
+      0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
+};
+
+/*
+ * Checkup routine
+ */
+int md5_self_test( int verbose )
+{
+    int i, buflen;
+    unsigned char buf[1024];
+    unsigned char md5sum[16];
+    md5_context ctx;
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            printf( "  MD5 test #%d: ", i + 1 );
+
+        md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
+
+        if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            printf( "  HMAC-MD5 test #%d: ", i + 1 );
+
+        if( i == 5 || i == 6 )
+        {
+            memset( buf, '\xAA', buflen = 80 );
+            md5_hmac_starts( &ctx, buf, buflen );
+        }
+        else
+            md5_hmac_starts( &ctx, md5_hmac_test_key[i],
+                                   md5_hmac_test_keylen[i] );
+
+        md5_hmac_update( &ctx, md5_hmac_test_buf[i],
+                               md5_hmac_test_buflen[i] );
+
+        md5_hmac_finish( &ctx, md5sum );
+
+        buflen = ( i == 4 ) ? 12 : 16;
+
+        if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 715 - 0
thirdparty/PolarSSL/library/md_wrap.c

@@ -0,0 +1,715 @@
+/**
+ * \file md_wrap.c
+
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md_wrap.h"
+#include "polarssl/md2.h"
+#include "polarssl/md4.h"
+#include "polarssl/md5.h"
+#include "polarssl/sha1.h"
+#include "polarssl/sha2.h"
+#include "polarssl/sha4.h"
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_MD2_C)
+
+static void md2_starts_wrap( void *ctx )
+{
+    md2_starts( (md2_context *) ctx );
+}
+
+static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    md2_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_finish_wrap( void *ctx, unsigned char *output )
+{
+    md2_finish( (md2_context *) ctx, output );
+}
+
+int md2_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return md2_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    md2_hmac_starts( (md2_context *) ctx, key, keylen );
+}
+
+static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    md2_hmac_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    md2_hmac_finish( (md2_context *) ctx, output );
+}
+
+static void md2_hmac_reset_wrap( void *ctx )
+{
+    md2_hmac_reset( (md2_context *) ctx );
+}
+
+static void * md2_ctx_alloc( void )
+{
+    return malloc( sizeof( md2_context ) );
+}
+
+static void md2_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t md2_info = {
+    POLARSSL_MD_MD2,
+    "MD2",
+    16,
+    md2_starts_wrap,
+    md2_update_wrap,
+    md2_finish_wrap,
+    md2,
+    md2_file_wrap,
+    md2_hmac_starts_wrap,
+    md2_hmac_update_wrap,
+    md2_hmac_finish_wrap,
+    md2_hmac_reset_wrap,
+    md2_hmac,
+    md2_ctx_alloc,
+    md2_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_MD4_C)
+
+void md4_starts_wrap( void *ctx )
+{
+    md4_starts( (md4_context *) ctx );
+}
+
+void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    md4_update( (md4_context *) ctx, input, ilen );
+}
+
+void md4_finish_wrap( void *ctx, unsigned char *output )
+{
+    md4_finish( (md4_context *) ctx, output );
+}
+
+int md4_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return md4_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    md4_hmac_starts( (md4_context *) ctx, key, keylen );
+}
+
+void md4_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    md4_hmac_update( (md4_context *) ctx, input, ilen );
+}
+
+void md4_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    md4_hmac_finish( (md4_context *) ctx, output );
+}
+
+void md4_hmac_reset_wrap( void *ctx )
+{
+    md4_hmac_reset( (md4_context *) ctx );
+}
+
+void *md4_ctx_alloc( void )
+{
+    return malloc( sizeof( md4_context ) );
+}
+
+void md4_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t md4_info = {
+    POLARSSL_MD_MD4,
+    "MD4",
+    16,
+    md4_starts_wrap,
+    md4_update_wrap,
+    md4_finish_wrap,
+    md4,
+    md4_file_wrap,
+    md4_hmac_starts_wrap,
+    md4_hmac_update_wrap,
+    md4_hmac_finish_wrap,
+    md4_hmac_reset_wrap,
+    md4_hmac,
+    md4_ctx_alloc,
+    md4_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_MD5_C)
+
+static void md5_starts_wrap( void *ctx )
+{
+    md5_starts( (md5_context *) ctx );
+}
+
+static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    md5_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_finish_wrap( void *ctx, unsigned char *output )
+{
+    md5_finish( (md5_context *) ctx, output );
+}
+
+int md5_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return md5_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    md5_hmac_starts( (md5_context *) ctx, key, keylen );
+}
+
+static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    md5_hmac_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    md5_hmac_finish( (md5_context *) ctx, output );
+}
+
+static void md5_hmac_reset_wrap( void *ctx )
+{
+    md5_hmac_reset( (md5_context *) ctx );
+}
+
+static void * md5_ctx_alloc( void )
+{
+    return malloc( sizeof( md5_context ) );
+}
+
+static void md5_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t md5_info = {
+    POLARSSL_MD_MD5,
+    "MD5",
+    16,
+    md5_starts_wrap,
+    md5_update_wrap,
+    md5_finish_wrap,
+    md5,
+    md5_file_wrap,
+    md5_hmac_starts_wrap,
+    md5_hmac_update_wrap,
+    md5_hmac_finish_wrap,
+    md5_hmac_reset_wrap,
+    md5_hmac,
+    md5_ctx_alloc,
+    md5_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+
+void sha1_starts_wrap( void *ctx )
+{
+    sha1_starts( (sha1_context *) ctx );
+}
+
+void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha1_update( (sha1_context *) ctx, input, ilen );
+}
+
+void sha1_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha1_finish( (sha1_context *) ctx, output );
+}
+
+int sha1_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha1_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    sha1_hmac_starts( (sha1_context *) ctx, key, keylen );
+}
+
+void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha1_hmac_update( (sha1_context *) ctx, input, ilen );
+}
+
+void sha1_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha1_hmac_finish( (sha1_context *) ctx, output );
+}
+
+void sha1_hmac_reset_wrap( void *ctx )
+{
+    sha1_hmac_reset( (sha1_context *) ctx );
+}
+
+void * sha1_ctx_alloc( void )
+{
+    return malloc( sizeof( sha1_context ) );
+}
+
+void sha1_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t sha1_info = {
+    POLARSSL_MD_SHA1,
+    "SHA1",
+    20,
+    sha1_starts_wrap,
+    sha1_update_wrap,
+    sha1_finish_wrap,
+    sha1,
+    sha1_file_wrap,
+    sha1_hmac_starts_wrap,
+    sha1_hmac_update_wrap,
+    sha1_hmac_finish_wrap,
+    sha1_hmac_reset_wrap,
+    sha1_hmac,
+    sha1_ctx_alloc,
+    sha1_ctx_free,
+};
+
+#endif
+
+/*
+ * Wrappers for generic message digests
+ */
+#if defined(POLARSSL_SHA2_C)
+
+void sha224_starts_wrap( void *ctx )
+{
+    sha2_starts( (sha2_context *) ctx, 1 );
+}
+
+void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha2_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha224_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha2_finish( (sha2_context *) ctx, output );
+}
+
+void sha224_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha2( input, ilen, output, 1 );
+}
+
+int sha224_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha2_file( path, output, 1 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 1 );
+}
+
+void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha2_hmac_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha224_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha2_hmac_finish( (sha2_context *) ctx, output );
+}
+
+void sha224_hmac_reset_wrap( void *ctx )
+{
+    sha2_hmac_reset( (sha2_context *) ctx );
+}
+
+void sha224_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha2_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+void * sha224_ctx_alloc( void )
+{
+    return malloc( sizeof( sha2_context ) );
+}
+
+void sha224_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t sha224_info = {
+    POLARSSL_MD_SHA224,
+    "SHA224",
+    28,
+    sha224_starts_wrap,
+    sha224_update_wrap,
+    sha224_finish_wrap,
+    sha224_wrap,
+    sha224_file_wrap,
+    sha224_hmac_starts_wrap,
+    sha224_hmac_update_wrap,
+    sha224_hmac_finish_wrap,
+    sha224_hmac_reset_wrap,
+    sha224_hmac_wrap,
+    sha224_ctx_alloc,
+    sha224_ctx_free,
+};
+
+void sha256_starts_wrap( void *ctx )
+{
+    sha2_starts( (sha2_context *) ctx, 0 );
+}
+
+void sha256_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha2_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha256_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha2_finish( (sha2_context *) ctx, output );
+}
+
+void sha256_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha2( input, ilen, output, 0 );
+}
+
+int sha256_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha2_file( path, output, 0 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 0 );
+}
+
+void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha2_hmac_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha256_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha2_hmac_finish( (sha2_context *) ctx, output );
+}
+
+void sha256_hmac_reset_wrap( void *ctx )
+{
+    sha2_hmac_reset( (sha2_context *) ctx );
+}
+
+void sha256_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha2_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+void * sha256_ctx_alloc( void )
+{
+    return malloc( sizeof( sha2_context ) );
+}
+
+void sha256_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t sha256_info = {
+    POLARSSL_MD_SHA256,
+    "SHA256",
+    32,
+    sha256_starts_wrap,
+    sha256_update_wrap,
+    sha256_finish_wrap,
+    sha256_wrap,
+    sha256_file_wrap,
+    sha256_hmac_starts_wrap,
+    sha256_hmac_update_wrap,
+    sha256_hmac_finish_wrap,
+    sha256_hmac_reset_wrap,
+    sha256_hmac_wrap,
+    sha256_ctx_alloc,
+    sha256_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+
+void sha384_starts_wrap( void *ctx )
+{
+    sha4_starts( (sha4_context *) ctx, 1 );
+}
+
+void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha4_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha384_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha4_finish( (sha4_context *) ctx, output );
+}
+
+void sha384_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha4( input, ilen, output, 1 );
+}
+
+int sha384_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha4_file( path, output, 1 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 1 );
+}
+
+void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha4_hmac_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha384_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha4_hmac_finish( (sha4_context *) ctx, output );
+}
+
+void sha384_hmac_reset_wrap( void *ctx )
+{
+    sha4_hmac_reset( (sha4_context *) ctx );
+}
+
+void sha384_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha4_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+void * sha384_ctx_alloc( void )
+{
+    return malloc( sizeof( sha4_context ) );
+}
+
+void sha384_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t sha384_info = {
+    POLARSSL_MD_SHA384,
+    "SHA384",
+    48,
+    sha384_starts_wrap,
+    sha384_update_wrap,
+    sha384_finish_wrap,
+    sha384_wrap,
+    sha384_file_wrap,
+    sha384_hmac_starts_wrap,
+    sha384_hmac_update_wrap,
+    sha384_hmac_finish_wrap,
+    sha384_hmac_reset_wrap,
+    sha384_hmac_wrap,
+    sha384_ctx_alloc,
+    sha384_ctx_free,
+};
+
+void sha512_starts_wrap( void *ctx )
+{
+    sha4_starts( (sha4_context *) ctx, 0 );
+}
+
+void sha512_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha4_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha512_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha4_finish( (sha4_context *) ctx, output );
+}
+
+void sha512_wrap( const unsigned char *input, size_t ilen,
+                    unsigned char *output )
+{
+    sha4( input, ilen, output, 0 );
+}
+
+int sha512_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return sha4_file( path, output, 0 );
+#else
+    ((void) path);
+    ((void) output);
+    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+    sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 0 );
+}
+
+void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+    sha4_hmac_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha512_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    sha4_hmac_finish( (sha4_context *) ctx, output );
+}
+
+void sha512_hmac_reset_wrap( void *ctx )
+{
+    sha4_hmac_reset( (sha4_context *) ctx );
+}
+
+void sha512_hmac_wrap( const unsigned char *key, size_t keylen,
+        const unsigned char *input, size_t ilen,
+        unsigned char *output )
+{
+    sha4_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+void * sha512_ctx_alloc( void )
+{
+    return malloc( sizeof( sha4_context ) );
+}
+
+void sha512_ctx_free( void *ctx )
+{
+    free( ctx );
+}
+
+const md_info_t sha512_info = {
+    POLARSSL_MD_SHA512,
+    "SHA512",
+    64,
+    sha512_starts_wrap,
+    sha512_update_wrap,
+    sha512_finish_wrap,
+    sha512_wrap,
+    sha512_file_wrap,
+    sha512_hmac_starts_wrap,
+    sha512_hmac_update_wrap,
+    sha512_hmac_finish_wrap,
+    sha512_hmac_reset_wrap,
+    sha512_hmac_wrap,
+    sha512_ctx_alloc,
+    sha512_ctx_free,
+};
+
+#endif
+
+#endif

+ 385 - 0
thirdparty/PolarSSL/library/net.c

@@ -0,0 +1,385 @@
+/*
+ *  TCP networking functions
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Note: This file has been modified by ST's MCD Application Team */
+
+#include "config.h"
+
+#if defined(POLARSSL_NET_C)
+
+#include "polarssl/net.h"
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+
+#include <winsock2.h>
+#include <windows.h>
+
+#if defined(_WIN32_WCE)
+#pragma comment( lib, "ws2.lib" )
+#else
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+
+#define read(fd,buf,len)        recv(fd,(char*)buf,(int) len,0)
+#define write(fd,buf,len)       send(fd,(char*)buf,(int) len,0)
+#define close(fd)               closesocket(fd)
+
+static int wsa_init_done = 0;
+
+#else
+#if  (!defined(__ICCARM__)) && (!defined(__CC_ARM)) && (!defined(__GNUC__)) && (!defined(__TASKING__))
+#include <sys/types.h>
+#endif
+#include "lwip/sockets.h"
+#include "lwip/inet.h"
+#if LWIP_DNS == 1
+#include "lwip/netdb.h"
+#endif
+//#include <sys/time.h>
+//#include <unistd.h>
+#include <signal.h>
+
+#if  (!defined(__ICCARM__)) && (!defined(__CC_ARM)) && (!defined(__GNUC__)) && (!defined(__TASKING__))
+#include <fcntl.h>
+#endif
+
+#include <errno.h>
+
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+#include <sys/endian.h>
+#elif defined(__APPLE__)
+#include <machine/endian.h>
+#else
+//#include <endian.h>
+#endif
+
+#endif
+
+#include <stdlib.h>
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#include <time.h>
+
+/*
+ * htons() is not always available.
+ * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and __BIG_ENDIAN
+ * to help determine endianess.
+ */
+#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
+#define POLARSSL_HTONS(n) (n)
+#else
+#define POLARSSL_HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
+#endif
+
+unsigned short net_htons(unsigned short n);
+#define net_htons(n) POLARSSL_HTONS(n)
+
+/*
+ * Initiate a TCP connection with host:port
+ */
+int net_connect( int *fd, const char *host, int port )
+{
+    struct sockaddr_in server_addr;
+#if LWIP_DNS == 1    
+    struct hostent *server_host;
+#endif
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+    WSADATA wsaData;
+
+    if( wsa_init_done == 0 )
+    {
+        if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+            return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+        wsa_init_done = 1;
+    }
+#else
+#if  (!defined(__ICCARM__)) && (!defined(__CC_ARM)) && (!defined(__GNUC__)) && (!defined(__TASKING__))
+    signal( SIGPIPE, SIG_IGN );
+#endif
+#endif
+#if LWIP_DNS == 1
+    if( ( server_host = gethostbyname( host ) ) == NULL ) {
+    	printf( "SSL: ! gethostbyname ERROR :" );
+    	printf(host);
+    	printf( "\n" );
+        return( POLARSSL_ERR_NET_UNKNOWN_HOST );
+       }
+    printf ( "SSL: gethostbyname OK\n" );
+    memcpy( (void *) &server_addr.sin_addr,
+                (void *) server_host->h_addr,
+                         server_host->h_length );
+#else
+    printf( "SSL: no DNS mode\n" );
+    memset(&server_addr, 0, sizeof(server_addr));
+    server_addr.sin_len         = sizeof(server_addr);
+    server_addr.sin_addr.s_addr = inet_addr(host);
+      
+#endif
+
+    if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+        return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port   = net_htons( port );
+
+    if( connect( *fd, (struct sockaddr *) &server_addr,
+                 sizeof( server_addr ) ) < 0 )
+    {
+        close( *fd );
+        return( POLARSSL_ERR_NET_CONNECT_FAILED );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Create a listening socket on bind_ip:port
+ */
+int net_bind( int *fd, const char *bind_ip, int port )
+{
+    int n, c[4];
+    struct sockaddr_in server_addr;
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+    WSADATA wsaData;
+
+    if( wsa_init_done == 0 )
+    {
+        if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+            return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+        wsa_init_done = 1;
+    }
+#else
+#if  (!defined(__ICCARM__)) && (!defined(__CC_ARM)) && (!defined(__GNUC__)) && (!defined(__TASKING__))
+    signal( SIGPIPE, SIG_IGN );
+#endif
+#endif
+
+    if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+        return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+    n = 1;
+    setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
+                (const char *) &n, sizeof( n ) );
+
+    server_addr.sin_addr.s_addr = INADDR_ANY;
+    server_addr.sin_family      = AF_INET;
+    server_addr.sin_port        = net_htons( port );
+
+    if( bind_ip != NULL )
+    {
+        memset( c, 0, sizeof( c ) );
+        sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
+
+        for( n = 0; n < 4; n++ )
+            if( c[n] < 0 || c[n] > 255 )
+                break;
+
+        if( n == 4 )
+            server_addr.sin_addr.s_addr =
+                ( (unsigned long) c[0] << 24 ) |
+                ( (unsigned long) c[1] << 16 ) |
+                ( (unsigned long) c[2] <<  8 ) |
+                ( (unsigned long) c[3]       );
+    }
+
+    if( bind( *fd, (struct sockaddr *) &server_addr,
+              sizeof( server_addr ) ) < 0 )
+    {
+        close( *fd );
+        return( POLARSSL_ERR_NET_BIND_FAILED );
+    }
+
+    if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
+    {
+        close( *fd );
+        return( POLARSSL_ERR_NET_LISTEN_FAILED );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Check if the current operation is blocking
+ */
+static int net_is_blocking( void )
+{
+#if defined(_WIN32) || defined(_WIN32_WCE)
+    return( WSAGetLastError() == WSAEWOULDBLOCK );
+#else
+    switch( errno )
+    {
+#if defined EAGAIN
+        case EAGAIN:
+#endif
+#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
+        case EWOULDBLOCK:
+#endif
+            return( 1 );
+    }
+    return( 0 );
+#endif
+}
+
+/*
+ * Accept a connection from a remote client
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip )
+{
+    struct sockaddr_in client_addr;
+
+#if defined(__socklen_t_defined) || defined(_SOCKLEN_T)
+    socklen_t n = (socklen_t) sizeof( client_addr );
+#else
+    int n = (int) sizeof( client_addr );
+#endif
+
+    *client_fd = accept( bind_fd, (struct sockaddr *)
+                         &client_addr, &n );
+
+    if( *client_fd < 0 )
+    {
+        if( net_is_blocking() != 0 )
+            return( POLARSSL_ERR_NET_WANT_READ );
+
+        return( POLARSSL_ERR_NET_ACCEPT_FAILED );
+    }
+
+    if( client_ip != NULL )
+        memcpy( client_ip, &client_addr.sin_addr.s_addr,
+                    sizeof( client_addr.sin_addr.s_addr ) );
+
+    return( 0 );
+}
+
+/*
+ * Set the socket blocking or non-blocking
+ */
+int net_set_block( int fd )
+{
+#if defined(WIN32) || defined(_WIN32_WCE) || defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) || defined(__TASKING__)
+    unsigned long n = 0;
+    return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+    return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
+#endif
+}
+
+int net_set_nonblock( int fd )
+{
+#if defined(WIN32) || defined(_WIN32_WCE) || defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) || defined(__TASKING__)
+    unsigned long n = 1;
+    return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+    return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
+#endif
+}
+
+/*
+ * Portable usleep helper
+ */
+void net_usleep( unsigned long usec )
+{
+    struct timeval tv;
+    tv.tv_sec  = 0;
+    tv.tv_usec = usec;
+    select( 0, NULL, NULL, NULL, &tv );
+}
+
+/*
+ * Read at most 'len' characters
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len )
+{ 
+    int ret = read( *((int *) ctx), buf, len );
+
+    if( ret < 0 )
+    {
+        if( net_is_blocking() != 0 )
+            return( POLARSSL_ERR_NET_WANT_READ );
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+        if( WSAGetLastError() == WSAECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+        if( errno == EPIPE || errno == ECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+
+        if( errno == EINTR )
+            return( POLARSSL_ERR_NET_WANT_READ );
+#endif
+
+        return( POLARSSL_ERR_NET_RECV_FAILED );
+    }
+
+    return( ret );
+}
+
+/*
+ * Write at most 'len' characters
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len )
+{
+    int ret = write( *((int *) ctx), buf, len );
+
+    if( ret < 0 )
+    {
+        if( net_is_blocking() != 0 )
+            return( POLARSSL_ERR_NET_WANT_WRITE );
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+        if( WSAGetLastError() == WSAECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+        if( errno == EPIPE || errno == ECONNRESET )
+            return( POLARSSL_ERR_NET_CONN_RESET );
+
+        if( errno == EINTR )
+            return( POLARSSL_ERR_NET_WANT_WRITE );
+#endif
+
+        return( POLARSSL_ERR_NET_SEND_FAILED );
+    }
+
+    return( ret );
+}
+
+/*
+ * Gracefully close the connection
+ */
+void net_close( int fd )
+{
+    shutdown( fd, 2 );
+    close( fd );
+}
+
+#endif

+ 162 - 0
thirdparty/PolarSSL/library/padlock.c

@@ -0,0 +1,162 @@
+/*
+ *  VIA PadLock support functions
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  This implementation is based on the VIA PadLock Programming Guide:
+ *
+ *  http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
+ *  programming_guide.pdf
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_PADLOCK_C)
+
+#include "polarssl/padlock.h"
+
+#if defined(POLARSSL_HAVE_X86)
+
+/*
+ * PadLock detection routine
+ */
+int padlock_supports( int feature )
+{
+    static int flags = -1;
+    int ebx, edx;
+
+    if( flags == -1 )
+    {
+        asm( "movl  %%ebx, %0           \n"     \
+             "movl  $0xC0000000, %%eax  \n"     \
+             "cpuid                     \n"     \
+             "cmpl  $0xC0000001, %%eax  \n"     \
+             "movl  $0, %%edx           \n"     \
+             "jb    unsupported         \n"     \
+             "movl  $0xC0000001, %%eax  \n"     \
+             "cpuid                     \n"     \
+             "unsupported:              \n"     \
+             "movl  %%edx, %1           \n"     \
+             "movl  %2, %%ebx           \n"
+             : "=m" (ebx), "=m" (edx)
+             :  "m" (ebx)
+             : "eax", "ecx", "edx" );
+
+        flags = edx;
+    }
+
+    return( flags & feature );
+}
+
+/*
+ * PadLock AES-ECB block en(de)cryption
+ */
+int padlock_xcryptecb( aes_context *ctx,
+                       int mode,
+                       const unsigned char input[16],
+                       unsigned char output[16] )
+{
+    int ebx;
+    unsigned long *rk;
+    unsigned long *blk;
+    unsigned long *ctrl;
+    unsigned char buf[256];
+
+    rk  = ctx->rk;
+    blk = PADLOCK_ALIGN16( buf );
+    memcpy( blk, input, 16 );
+
+     ctrl = blk + 4;
+    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
+
+    asm( "pushfl; popfl         \n"     \
+         "movl    %%ebx, %0     \n"     \
+         "movl    $1, %%ecx     \n"     \
+         "movl    %2, %%edx     \n"     \
+         "movl    %3, %%ebx     \n"     \
+         "movl    %4, %%esi     \n"     \
+         "movl    %4, %%edi     \n"     \
+         ".byte  0xf3,0x0f,0xa7,0xc8\n" \
+         "movl    %1, %%ebx     \n"
+         : "=m" (ebx)
+         :  "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
+         : "ecx", "edx", "esi", "edi" );
+
+    memcpy( output, blk, 16 );
+
+    return( 0 );
+}
+
+/*
+ * PadLock AES-CBC buffer en(de)cryption
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int ebx;
+    size_t count;
+    unsigned long *rk;
+    unsigned long *iw;
+    unsigned long *ctrl;
+    unsigned char buf[256];
+
+    if( ( (long) input  & 15 ) != 0 ||
+        ( (long) output & 15 ) != 0 )
+        return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED );
+
+    rk = ctx->rk;
+    iw = PADLOCK_ALIGN16( buf );
+    memcpy( iw, iv, 16 );
+
+     ctrl = iw + 4;
+    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
+
+    count = (length + 15) >> 4;
+
+    asm( "pushfl; popfl         \n"     \
+         "movl    %%ebx, %0     \n"     \
+         "movl    %2, %%ecx     \n"     \
+         "movl    %3, %%edx     \n"     \
+         "movl    %4, %%ebx     \n"     \
+         "movl    %5, %%esi     \n"     \
+         "movl    %6, %%edi     \n"     \
+         "movl    %7, %%eax     \n"     \
+         ".byte  0xf3,0x0f,0xa7,0xd0\n" \
+         "movl    %1, %%ebx     \n"
+         : "=m" (ebx)
+         :  "m" (ebx), "m" (count), "m" (ctrl),
+            "m"  (rk), "m" (input), "m" (output), "m" (iw)
+         : "eax", "ecx", "edx", "esi", "edi" );
+
+    memcpy( iv, iw, 16 );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 350 - 0
thirdparty/PolarSSL/library/pem.c

@@ -0,0 +1,350 @@
+/*
+ *  Privacy Enhanced Mail (PEM) decoding
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_PEM_C)
+
+#include "polarssl/pem.h"
+#include "polarssl/base64.h"
+#include "polarssl/des.h"
+#include "polarssl/aes.h"
+#include "polarssl/md5.h"
+#include "polarssl/cipher.h"
+
+#include <stdlib.h>
+
+void pem_init( pem_context *ctx )
+{
+    memset( ctx, 0, sizeof( pem_context ) );
+}
+
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+/*
+ * Read a 16-byte hex string and convert it to binary
+ */
+static int pem_get_iv( const unsigned char *s, unsigned char *iv, size_t iv_len )
+{
+    size_t i, j, k;
+
+    memset( iv, 0, iv_len );
+
+    for( i = 0; i < iv_len * 2; i++, s++ )
+    {
+        if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
+        if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
+        if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
+            return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+        k = ( ( i & 1 ) != 0 ) ? j : j << 4;
+
+        iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
+    }
+
+    return( 0 );
+}
+
+static void pem_pbkdf1( unsigned char *key, size_t keylen,
+                        unsigned char *iv,
+                        const unsigned char *pwd, size_t pwdlen )
+{
+    md5_context md5_ctx;
+    unsigned char md5sum[16];
+    size_t use_len;
+
+    /*
+     * key[ 0..15] = MD5(pwd || IV)
+     */
+    md5_starts( &md5_ctx );
+    md5_update( &md5_ctx, pwd, pwdlen );
+    md5_update( &md5_ctx, iv,  8 );
+    md5_finish( &md5_ctx, md5sum );
+
+    if( keylen <= 16 )
+    {
+        memcpy( key, md5sum, keylen );
+
+        memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
+        memset( md5sum, 0, 16 );
+        return;
+    }
+
+    memcpy( key, md5sum, 16 );
+
+    /*
+     * key[16..23] = MD5(key[ 0..15] || pwd || IV])
+     */
+    md5_starts( &md5_ctx );
+    md5_update( &md5_ctx, md5sum,  16 );
+    md5_update( &md5_ctx, pwd, pwdlen );
+    md5_update( &md5_ctx, iv,  8 );
+    md5_finish( &md5_ctx, md5sum );
+
+    use_len = 16;
+    if( keylen < 32 )
+        use_len = keylen - 16;
+
+    memcpy( key + 16, md5sum, use_len );
+
+    memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
+    memset( md5sum, 0, 16 );
+}
+
+#if defined(POLARSSL_DES_C)
+/*
+ * Decrypt with DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des_decrypt( unsigned char des_iv[8],
+                               unsigned char *buf, size_t buflen,
+                               const unsigned char *pwd, size_t pwdlen )
+{
+    des_context des_ctx;
+    unsigned char des_key[8];
+
+    pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
+
+    des_setkey_dec( &des_ctx, des_key );
+    des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
+                     des_iv, buf, buf );
+
+    memset( &des_ctx, 0, sizeof( des_ctx ) );
+    memset( des_key, 0, 8 );
+}
+
+/*
+ * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des3_decrypt( unsigned char des3_iv[8],
+                               unsigned char *buf, size_t buflen,
+                               const unsigned char *pwd, size_t pwdlen )
+{
+    des3_context des3_ctx;
+    unsigned char des3_key[24];
+
+    pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
+
+    des3_set3key_dec( &des3_ctx, des3_key );
+    des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
+                     des3_iv, buf, buf );
+
+    memset( &des3_ctx, 0, sizeof( des3_ctx ) );
+    memset( des3_key, 0, 24 );
+}
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+/*
+ * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
+ */
+static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
+                               unsigned char *buf, size_t buflen,
+                               const unsigned char *pwd, size_t pwdlen )
+{
+    aes_context aes_ctx;
+    unsigned char aes_key[32];
+
+    pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
+
+    aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
+    aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
+                     aes_iv, buf, buf );
+
+    memset( &aes_ctx, 0, sizeof( aes_ctx ) );
+    memset( aes_key, 0, keylen );
+}
+#endif /* POLARSSL_AES_C */
+
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+
+int pem_read_buffer( pem_context *ctx, char *header, char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len )
+{
+    int ret, enc;
+    size_t len;
+    unsigned char *buf;
+    unsigned char *s1, *s2;
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+    unsigned char pem_iv[16];
+    cipher_type_t enc_alg = POLARSSL_CIPHER_NONE;
+#else
+    ((void) pwd);
+    ((void) pwdlen);
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+
+    if( ctx == NULL )
+        return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+    s1 = (unsigned char *) strstr( (char *) data, header );
+
+    if( s1 == NULL )
+        return( POLARSSL_ERR_PEM_NO_HEADER_PRESENT );
+
+    s2 = (unsigned char *) strstr( (char *) data, footer );
+
+    if( s2 == NULL || s2 <= s1 )
+        return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+    s1 += strlen( header );
+    if( *s1 == '\r' ) s1++;
+    if( *s1 == '\n' ) s1++;
+    else return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+    enc = 0;
+
+    if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
+    {
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+        enc++;
+
+        s1 += 22;
+        if( *s1 == '\r' ) s1++;
+        if( *s1 == '\n' ) s1++;
+        else return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+
+#if defined(POLARSSL_DES_C)
+        if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
+        {
+            enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC;
+
+            s1 += 23;
+            if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
+                return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+            s1 += 16;
+        }
+        else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
+        {
+            enc_alg = POLARSSL_CIPHER_DES_CBC;
+
+            s1 += 18;
+            if( pem_get_iv( s1, pem_iv, 8) != 0 )
+                return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+            s1 += 16;
+        }
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+        if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
+        {
+            if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
+                enc_alg = POLARSSL_CIPHER_AES_128_CBC;
+            else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
+                enc_alg = POLARSSL_CIPHER_AES_192_CBC;
+            else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
+                enc_alg = POLARSSL_CIPHER_AES_256_CBC;
+            else
+                return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+            s1 += 22;
+            if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
+                return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+            s1 += 32;
+        }
+#endif /* POLARSSL_AES_C */
+        
+        if( enc_alg == POLARSSL_CIPHER_NONE )
+            return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+        if( *s1 == '\r' ) s1++;
+        if( *s1 == '\n' ) s1++;
+        else return( POLARSSL_ERR_PEM_INVALID_DATA );
+#else
+        return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+    }
+
+    len = 0;
+    ret = base64_decode( NULL, &len, s1, s2 - s1 );
+
+    if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
+        return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+
+    if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
+        return( POLARSSL_ERR_PEM_MALLOC_FAILED );
+
+    if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
+    {
+        free( buf );
+        return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+    }
+    
+    if( enc != 0 )
+    {
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+        if( pwd == NULL )
+        {
+            free( buf );
+            return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED );
+        }
+
+#if defined(POLARSSL_DES_C)
+        if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC )
+            pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
+        else if( enc_alg == POLARSSL_CIPHER_DES_CBC )
+            pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+        if( enc_alg == POLARSSL_CIPHER_AES_128_CBC )
+            pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
+        else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC )
+            pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
+        else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC )
+            pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_AES_C */
+
+        if( buf[0] != 0x30 || buf[1] != 0x82 ||
+            buf[4] != 0x02 || buf[5] != 0x01 )
+        {
+            free( buf );
+            return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH );
+        }
+#else
+        return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif
+    }
+
+    ctx->buf = buf;
+    ctx->buflen = len;
+    s2 += strlen( footer );
+    if( *s2 == '\r' ) s2++;
+    if( *s2 == '\n' ) s2++;
+    *use_len = s2 - data;
+
+    return( 0 );
+}
+
+void pem_free( pem_context *ctx )
+{
+    if( ctx->buf )
+        free( ctx->buf );
+
+    if( ctx->info )
+        free( ctx->info );
+}
+
+#endif

+ 238 - 0
thirdparty/PolarSSL/library/pkcs11.c

@@ -0,0 +1,238 @@
+/**
+ * \file pkcs11.c
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/pkcs11.h"
+
+#if defined(POLARSSL_PKCS11_C)
+
+#include <stdlib.h>
+
+int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11_cert )
+{
+    int ret = 1;
+    unsigned char *cert_blob = NULL;
+    size_t cert_blob_size = 0;
+
+    if( cert == NULL )
+    {
+        ret = 2;
+        goto cleanup;
+    }
+
+    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, &cert_blob_size ) != CKR_OK )
+    {
+        ret = 3;
+        goto cleanup;
+    }
+
+    cert_blob = malloc( cert_blob_size );
+    if( NULL == cert_blob )
+    {
+        ret = 4;
+        goto cleanup;
+    }
+
+    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, &cert_blob_size ) != CKR_OK )
+    {
+        ret = 5;
+        goto cleanup;
+    }
+
+    if( 0 != x509parse_crt(cert, cert_blob, cert_blob_size ) )
+    {
+        ret = 6;
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    if( NULL != cert_blob )
+        free( cert_blob );
+
+    return ret;
+}
+
+
+int pkcs11_priv_key_init( pkcs11_context *priv_key,
+        pkcs11h_certificate_t pkcs11_cert )
+{
+    int ret = 1;
+    x509_cert cert;
+
+    memset( &cert, 0, sizeof( cert ) );
+
+    if( priv_key == NULL )
+        goto cleanup;
+
+    if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) )
+        goto cleanup;
+
+    priv_key->len = cert.rsa.len;
+    priv_key->pkcs11h_cert = pkcs11_cert;
+
+    ret = 0;
+
+cleanup:
+    x509_free( &cert );
+
+    return ret;
+}
+
+void pkcs11_priv_key_free( pkcs11_context *priv_key )
+{
+    if( NULL != priv_key )
+        pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert );
+}
+
+int pkcs11_decrypt( pkcs11_context *ctx,
+                       int mode, size_t *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       unsigned int output_max_len )
+{
+    size_t input_len, output_len;
+
+    if( NULL == ctx )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( RSA_PUBLIC == mode )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    output_len = input_len = ctx->len;
+
+    if( input_len < 16 || input_len > output_max_len )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    /* Determine size of output buffer */
+    if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+            input_len, NULL, &output_len ) != CKR_OK )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    if( output_len > output_max_len )
+        return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+    if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+            input_len, output, &output_len ) != CKR_OK )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+    *olen = output_len;
+    return( 0 );
+}
+
+int pkcs11_sign( pkcs11_context *ctx,
+                    int mode,
+                    int hash_id,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig )
+{
+    size_t olen, asn_len;
+    unsigned char *p = sig;
+
+    if( NULL == ctx )
+        return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+    if( RSA_PUBLIC == mode )
+        return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+    olen = ctx->len;
+
+    switch( hash_id )
+    {
+        case SIG_RSA_RAW:
+            asn_len = 0;
+            memcpy( p, hash, hashlen );
+            break;
+
+        case SIG_RSA_MD2:
+            asn_len = OID_SIZE(ASN1_HASH_MDX);
+            memcpy( p, ASN1_HASH_MDX, asn_len );
+            memcpy( p + asn_len, hash, hashlen );
+            p[13] = 2; break;
+
+        case SIG_RSA_MD4:
+            asn_len = OID_SIZE(ASN1_HASH_MDX);
+            memcpy( p, ASN1_HASH_MDX, asn_len );
+            memcpy( p + asn_len, hash, hashlen );
+            p[13] = 4; break;
+
+        case SIG_RSA_MD5:
+            asn_len = OID_SIZE(ASN1_HASH_MDX);
+            memcpy( p, ASN1_HASH_MDX, asn_len );
+            memcpy( p + asn_len, hash, hashlen );
+            p[13] = 5; break;
+
+        case SIG_RSA_SHA1:
+            asn_len = OID_SIZE(ASN1_HASH_SHA1);
+            memcpy( p, ASN1_HASH_SHA1, asn_len );
+            memcpy( p + 15, hash, hashlen );
+            break;
+
+        case SIG_RSA_SHA224:
+            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+            memcpy( p, ASN1_HASH_SHA2X, asn_len );
+            memcpy( p + asn_len, hash, hashlen );
+            p[1] += hashlen; p[14] = 4; p[18] += hashlen; break;
+
+        case SIG_RSA_SHA256:
+            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+            memcpy( p, ASN1_HASH_SHA2X, asn_len );
+            memcpy( p + asn_len, hash, hashlen );
+            p[1] += hashlen; p[14] = 1; p[18] += hashlen; break;
+
+        case SIG_RSA_SHA384:
+            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+            memcpy( p, ASN1_HASH_SHA2X, asn_len );
+            memcpy( p + asn_len, hash, hashlen );
+            p[1] += hashlen; p[14] = 2; p[18] += hashlen; break;
+
+        case SIG_RSA_SHA512:
+            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+            memcpy( p, ASN1_HASH_SHA2X, asn_len );
+            memcpy( p + asn_len, hash, hashlen );
+            p[1] += hashlen; p[14] = 3; p[18] += hashlen; break;
+
+        default:
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
+            asn_len + hashlen, sig, &olen ) != CKR_OK )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    return( 0 );
+}
+
+#endif /* defined(POLARSSL_PKCS11_C) */

+ 1206 - 0
thirdparty/PolarSSL/library/rsa.c

@@ -0,0 +1,1206 @@
+/*
+ *  The RSA public-key cryptosystem
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
+ *
+ *  http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
+ *  http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_RSA_C)
+
+#include "polarssl/rsa.h"
+#include "polarssl/md.h"
+
+#include <stdlib.h>
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+
+/*
+ * Initialize an RSA context
+ */
+void rsa_init( rsa_context *ctx,
+               int padding,
+               int hash_id )
+{
+    memset( ctx, 0, sizeof( rsa_context ) );
+
+    ctx->padding = padding;
+    ctx->hash_id = hash_id;
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Generate an RSA keypair
+ */
+int rsa_gen_key( rsa_context *ctx,
+        int (*f_rng)(void *),
+        void *p_rng,
+        unsigned int nbits, int exponent )
+{
+    int ret;
+    mpi P1, Q1, H, G;
+
+    if( f_rng == NULL || nbits < 128 || exponent < 3 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G );
+
+    /*
+     * find primes P and Q with Q < P so that:
+     * GCD( E, (P-1)*(Q-1) ) == 1
+     */
+    MPI_CHK( mpi_lset( &ctx->E, exponent ) );
+
+    do
+    {
+        MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, 
+                                f_rng, p_rng ) );
+
+        MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
+                                f_rng, p_rng ) );
+
+        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
+            mpi_swap( &ctx->P, &ctx->Q );
+
+        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
+            continue;
+
+        MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+        if( mpi_msb( &ctx->N ) != nbits )
+            continue;
+
+        MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+        MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+        MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+        MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
+    }
+    while( mpi_cmp_int( &G, 1 ) != 0 );
+
+    /*
+     * D  = E^-1 mod ((P-1)*(Q-1))
+     * DP = D mod (P - 1)
+     * DQ = D mod (Q - 1)
+     * QP = Q^-1 mod P
+     */
+    MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H  ) );
+    MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
+    MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
+    MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
+
+    ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
+
+cleanup:
+
+    mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G );
+
+    if( ret != 0 )
+    {
+        rsa_free( ctx );
+        return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret );
+    }
+
+    return( 0 );   
+}
+
+#endif
+
+/*
+ * Check a public RSA key
+ */
+int rsa_check_pubkey( const rsa_context *ctx )
+{
+    if( !ctx->N.p || !ctx->E.p )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( ( ctx->N.p[0] & 1 ) == 0 || 
+        ( ctx->E.p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( mpi_msb( &ctx->N ) < 128 ||
+        mpi_msb( &ctx->N ) > 4096 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( mpi_msb( &ctx->E ) < 2 ||
+        mpi_msb( &ctx->E ) > 64 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    return( 0 );
+}
+
+/*
+ * Check a private RSA key
+ */
+int rsa_check_privkey( const rsa_context *ctx )
+{
+    int ret;
+    mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2;
+
+    if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
+        return( ret );
+
+    if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 );
+    mpi_init( &H  ); mpi_init( &I  ); mpi_init( &G  ); mpi_init( &G2 );
+    mpi_init( &L1 ); mpi_init( &L2 );
+
+    MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
+    MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
+    MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+    MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+    MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+    MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
+
+    MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
+    MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );  
+    MPI_CHK( mpi_mod_mpi( &I, &DE, &L1  ) );
+
+    /*
+     * Check for a valid PKCS1v2 private key
+     */
+    if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
+        mpi_cmp_int( &L2, 0 ) != 0 ||
+        mpi_cmp_int( &I, 1 ) != 0 ||
+        mpi_cmp_int( &G, 1 ) != 0 )
+    {
+        ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED;
+    }
+
+    
+cleanup:
+
+    mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 );
+    mpi_free( &H  ); mpi_free( &I  ); mpi_free( &G  ); mpi_free( &G2 );
+    mpi_free( &L1 ); mpi_free( &L2 );
+
+    if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED )
+        return( ret );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int rsa_public( rsa_context *ctx,
+                const unsigned char *input,
+                unsigned char *output )
+{
+    int ret;
+    size_t olen;
+    mpi T;
+
+    mpi_init( &T );
+
+    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+    {
+        mpi_free( &T );
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    olen = ctx->len;
+    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+    mpi_free( &T );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );
+
+    return( 0 );
+}
+
+/*
+ * Do an RSA private key operation
+ */
+int rsa_private( rsa_context *ctx,
+                 const unsigned char *input,
+                 unsigned char *output )
+{
+    int ret;
+    size_t olen;
+    mpi T, T1, T2;
+
+    mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
+
+    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+    {
+        mpi_free( &T );
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+#if defined(POLARSSL_RSA_NO_CRT)
+    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+#else
+    /*
+     * faster decryption using the CRT
+     *
+     * T1 = input ^ dP mod P
+     * T2 = input ^ dQ mod Q
+     */
+    MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
+    MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
+
+    /*
+     * T = (T1 - T2) * (Q^-1 mod P) mod P
+     */
+    MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
+    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
+    MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
+
+    /*
+     * output = T2 + T * Q
+     */
+    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
+    MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
+#endif
+
+    olen = ctx->len;
+    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+    mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/**
+ * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
+ *
+ * @param dst       buffer to mask
+ * @param dlen      length of destination buffer
+ * @param src       source of the mask generation
+ * @param slen      length of the source buffer
+ * @param md_ctx    message digest context to use
+ */
+static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen,  
+                       md_context_t *md_ctx )
+{
+    unsigned char mask[POLARSSL_MD_MAX_SIZE];
+    unsigned char counter[4];
+    unsigned char *p;
+    unsigned int hlen;
+    size_t i, use_len;
+
+    memset( mask, 0, POLARSSL_MD_MAX_SIZE );
+    memset( counter, 0, 4 );
+
+    hlen = md_ctx->md_info->size;
+
+    // Generate and apply dbMask
+    //
+    p = dst;
+
+    while( dlen > 0 )
+    {
+        use_len = hlen;
+        if( dlen < hlen )
+            use_len = dlen;
+
+        md_starts( md_ctx );
+        md_update( md_ctx, src, slen );
+        md_update( md_ctx, counter, 4 );
+        md_finish( md_ctx, mask );
+
+        for( i = 0; i < use_len; ++i )
+            *p++ ^= mask[i];
+
+        counter[3]++;
+
+        dlen -= use_len;
+    }
+}
+#endif
+
+/*
+ * Add the message padding, then do an RSA operation
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+                       int (*f_rng)(void *),
+                       void *p_rng,
+                       int mode, size_t ilen,
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    size_t nb_pad, olen;
+    unsigned char *p = output;
+#if defined(POLARSSL_PKCS1_V21)
+    unsigned int i, hlen;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+#endif
+
+    olen = ctx->len;
+
+    if( f_rng == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            if( olen < ilen + 11 )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            nb_pad = olen - 3 - ilen;
+
+            *p++ = 0;
+            *p++ = RSA_CRYPT;
+
+            while( nb_pad-- > 0 )
+            {
+                int rng_dl = 100;
+
+                do {
+                    *p = (unsigned char) f_rng( p_rng );
+                } while( *p == 0 && --rng_dl );
+
+                // Check if RNG failed to generate data
+                //
+                if( rng_dl == 0 )
+                    return POLARSSL_ERR_RSA_RNG_FAILED;
+
+                p++;
+            }
+            *p++ = 0;
+            memcpy( p, input, ilen );
+            break;
+        
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+
+            md_info = md_info_from_type( ctx->hash_id );
+            if( md_info == NULL )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            hlen = md_get_size( md_info );
+
+            if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            memset( output, 0, olen );
+            memset( &md_ctx, 0, sizeof( md_context_t ) );
+
+            md_init_ctx( &md_ctx, md_info );
+
+            *p++ = 0;
+
+            // Generate a random octet string seed
+            //
+            for( i = 0; i < hlen; ++i )
+                *p++ = (unsigned char) f_rng( p_rng ); 
+
+            // Construct DB
+            //
+            md( md_info, p, 0, p );
+            p += hlen;
+            p += olen - 2 * hlen - 2 - ilen;
+            *p++ = 1;
+            memcpy( p, input, ilen ); 
+
+            // maskedDB: Apply dbMask to DB
+            //
+            mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,  
+                       &md_ctx );
+
+            // maskedSeed: Apply seedMask to seed
+            //
+            mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,  
+                       &md_ctx );
+            break;
+#endif
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, output, output )
+            : rsa_private( ctx, output, output ) );
+}
+
+/*
+ * Do an RSA operation, then remove the message padding
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+                       int mode, size_t *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       size_t output_max_len)
+{
+    int ret;
+    size_t ilen;
+    unsigned char *p;
+    unsigned char buf[1024];
+#if defined(POLARSSL_PKCS1_V21)
+    unsigned char lhash[POLARSSL_MD_MAX_SIZE];
+    unsigned int hlen;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+#endif
+
+    ilen = ctx->len;
+
+    if( ilen < 16 || ilen > sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, input, buf )
+          : rsa_private( ctx, input, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    p = buf;
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            if( *p++ != 0 || *p++ != RSA_CRYPT )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            while( *p != 0 )
+            {
+                if( p >= buf + ilen - 1 )
+                    return( POLARSSL_ERR_RSA_INVALID_PADDING );
+                p++;
+            }
+            p++;
+            break;
+
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+            
+            if( *p++ != 0 )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            md_info = md_info_from_type( ctx->hash_id );
+            if( md_info == NULL )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+                
+            hlen = md_get_size( md_info );
+            memset( &md_ctx, 0, sizeof( md_context_t ) );
+
+            md_init_ctx( &md_ctx, md_info );
+            
+            // Generate lHash
+            //
+            md( md_info, lhash, 0, lhash );
+
+            // seed: Apply seedMask to maskedSeed
+            //
+            mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
+                       &md_ctx );
+
+            // DB: Apply dbMask to maskedDB
+            //
+            mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,  
+                       &md_ctx );
+
+            p += hlen;
+
+            // Check validity
+            //
+            if( memcmp( lhash, p, hlen ) != 0 )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            p += hlen;
+
+            while( *p == 0 && p < buf + ilen )
+                p++;
+
+            if( p == buf + ilen )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            if( *p++ != 0x01 )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            break;
+#endif
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    if (ilen - (p - buf) > output_max_len)
+        return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+    *olen = ilen - (p - buf);
+    memcpy( output, p, *olen );
+
+    return( 0 );
+}
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+                    int (*f_rng)(void *),
+                    void *p_rng,
+                    int mode,
+                    int hash_id,
+                    unsigned int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig )
+{
+    size_t nb_pad, olen;
+    unsigned char *p = sig;
+#if defined(POLARSSL_PKCS1_V21)
+    unsigned char salt[POLARSSL_MD_MAX_SIZE];
+    unsigned int i, slen, hlen, offset = 0;
+    size_t msb;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+#else
+    (void) f_rng;
+    (void) p_rng;
+#endif
+
+    olen = ctx->len;
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            switch( hash_id )
+            {
+                case SIG_RSA_RAW:
+                    nb_pad = olen - 3 - hashlen;
+                    break;
+
+                case SIG_RSA_MD2:
+                case SIG_RSA_MD4:
+                case SIG_RSA_MD5:
+                    nb_pad = olen - 3 - 34;
+                    break;
+
+                case SIG_RSA_SHA1:
+                    nb_pad = olen - 3 - 35;
+                    break;
+
+                case SIG_RSA_SHA224:
+                    nb_pad = olen - 3 - 47;
+                    break;
+
+                case SIG_RSA_SHA256:
+                    nb_pad = olen - 3 - 51;
+                    break;
+
+                case SIG_RSA_SHA384:
+                    nb_pad = olen - 3 - 67;
+                    break;
+
+                case SIG_RSA_SHA512:
+                    nb_pad = olen - 3 - 83;
+                    break;
+
+
+                default:
+                    return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+            }
+
+            if( nb_pad < 8 )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            *p++ = 0;
+            *p++ = RSA_SIGN;
+            memset( p, 0xFF, nb_pad );
+            p += nb_pad;
+            *p++ = 0;
+
+            switch( hash_id )
+            {
+                case SIG_RSA_RAW:
+                    memcpy( p, hash, hashlen );
+                    break;
+
+                case SIG_RSA_MD2:
+                    memcpy( p, ASN1_HASH_MDX, 18 );
+                    memcpy( p + 18, hash, 16 );
+                    p[13] = 2; break;
+
+                case SIG_RSA_MD4:
+                    memcpy( p, ASN1_HASH_MDX, 18 );
+                    memcpy( p + 18, hash, 16 );
+                    p[13] = 4; break;
+
+                case SIG_RSA_MD5:
+                    memcpy( p, ASN1_HASH_MDX, 18 );
+                    memcpy( p + 18, hash, 16 );
+                    p[13] = 5; break;
+
+                case SIG_RSA_SHA1:
+                    memcpy( p, ASN1_HASH_SHA1, 15 );
+                    memcpy( p + 15, hash, 20 );
+                    break;
+
+                case SIG_RSA_SHA224:
+                    memcpy( p, ASN1_HASH_SHA2X, 19 );
+                    memcpy( p + 19, hash, 28 );
+                    p[1] += 28; p[14] = 4; p[18] += 28; break;
+
+                case SIG_RSA_SHA256:
+                    memcpy( p, ASN1_HASH_SHA2X, 19 );
+                    memcpy( p + 19, hash, 32 );
+                    p[1] += 32; p[14] = 1; p[18] += 32; break;
+
+                case SIG_RSA_SHA384:
+                    memcpy( p, ASN1_HASH_SHA2X, 19 );
+                    memcpy( p + 19, hash, 48 );
+                    p[1] += 48; p[14] = 2; p[18] += 48; break;
+
+                case SIG_RSA_SHA512:
+                    memcpy( p, ASN1_HASH_SHA2X, 19 );
+                    memcpy( p + 19, hash, 64 );
+                    p[1] += 64; p[14] = 3; p[18] += 64; break;
+
+                default:
+                    return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+            }
+
+            break;
+
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+
+            if( f_rng == NULL )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            switch( hash_id )
+            {
+                case SIG_RSA_MD2:
+                case SIG_RSA_MD4:
+                case SIG_RSA_MD5:
+                    hashlen = 16;
+                    break;
+
+                case SIG_RSA_SHA1:
+                    hashlen = 20;
+                    break;
+
+                case SIG_RSA_SHA224:
+                    hashlen = 28;
+                    break;
+
+                case SIG_RSA_SHA256:
+                    hashlen = 32;
+                    break;
+
+                case SIG_RSA_SHA384:
+                    hashlen = 48;
+                    break;
+
+                case SIG_RSA_SHA512:
+                    hashlen = 64;
+                    break;
+
+                default:
+                    return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+            }
+
+            md_info = md_info_from_type( ctx->hash_id );
+            if( md_info == NULL )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+                
+            hlen = md_get_size( md_info );
+            slen = hlen;
+
+            memset( sig, 0, olen );
+            memset( &md_ctx, 0, sizeof( md_context_t ) );
+
+            md_init_ctx( &md_ctx, md_info );
+
+            msb = mpi_msb( &ctx->N ) - 1;
+
+            // Generate salt of length slen
+            //
+            for( i = 0; i < slen; ++i )
+                salt[i] = (unsigned char) f_rng( p_rng ); 
+
+            // Note: EMSA-PSS encoding is over the length of N - 1 bits
+            //
+            msb = mpi_msb( &ctx->N ) - 1;
+            p += olen - hlen * 2 - 2;
+            *p++ = 0x01;
+            memcpy( p, salt, slen );
+            p += slen;
+
+            // Generate H = Hash( M' )
+            //
+            md_starts( &md_ctx );
+            md_update( &md_ctx, p, 8 );
+            md_update( &md_ctx, hash, hashlen );
+            md_update( &md_ctx, salt, slen );
+            md_finish( &md_ctx, p );
+
+            // Compensate for boundary condition when applying mask
+            //
+            if( msb % 8 == 0 )
+                offset = 1;
+
+            // maskedDB: Apply dbMask to DB
+            //
+            mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
+
+            msb = mpi_msb( &ctx->N ) - 1;
+            sig[0] &= 0xFF >> ( olen * 8 - msb );
+
+            p += hlen;
+            *p++ = 0xBC;
+            break;
+#endif
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, sig, sig )
+            : rsa_private( ctx, sig, sig ) );
+}
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+                      int mode,
+                      int hash_id,
+                      unsigned int hashlen,
+                      const unsigned char *hash,
+                      unsigned char *sig )
+{
+    int ret;
+    size_t len, siglen;
+    unsigned char *p, c;
+    unsigned char buf[1024];
+#if defined(POLARSSL_PKCS1_V21)
+    unsigned char zeros[8];
+    unsigned int hlen;
+    size_t slen, msb;
+    const md_info_t *md_info;
+    md_context_t md_ctx;
+#endif
+    siglen = ctx->len;
+
+    if( siglen < 16 || siglen > sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, sig, buf )
+          : rsa_private( ctx, sig, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    p = buf;
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            if( *p++ != 0 || *p++ != RSA_SIGN )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            while( *p != 0 )
+            {
+                if( p >= buf + siglen - 1 || *p != 0xFF )
+                    return( POLARSSL_ERR_RSA_INVALID_PADDING );
+                p++;
+            }
+            p++;
+
+            len = siglen - ( p - buf );
+
+            if( len == 34 )
+            {
+                c = p[13];
+                p[13] = 0;
+
+                if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
+                    return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+                if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
+                        ( c == 4 && hash_id == SIG_RSA_MD4 ) ||
+                        ( c == 5 && hash_id == SIG_RSA_MD5 ) )
+                {
+                    if( memcmp( p + 18, hash, 16 ) == 0 ) 
+                        return( 0 );
+                    else
+                        return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+                }
+            }
+
+            if( len == 35 && hash_id == SIG_RSA_SHA1 )
+            {
+                if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
+                        memcmp( p + 15, hash, 20 ) == 0 )
+                    return( 0 );
+                else
+                    return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+            }
+            if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
+                    ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
+                    ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
+                    ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
+            {
+                c = p[1] - 17;
+                p[1] = 17;
+                p[14] = 0;
+
+                if( p[18] == c &&
+                        memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
+                        memcmp( p + 19, hash, c ) == 0 )
+                    return( 0 );
+                else
+                    return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+            }
+
+            if( len == hashlen && hash_id == SIG_RSA_RAW )
+            {
+                if( memcmp( p, hash, hashlen ) == 0 )
+                    return( 0 );
+                else
+                    return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+            }
+
+            break;
+
+#if defined(POLARSSL_PKCS1_V21)
+        case RSA_PKCS_V21:
+            
+            if( buf[siglen - 1] != 0xBC )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            switch( hash_id )
+            {
+                case SIG_RSA_MD2:
+                case SIG_RSA_MD4:
+                case SIG_RSA_MD5:
+                    hashlen = 16;
+                    break;
+
+                case SIG_RSA_SHA1:
+                    hashlen = 20;
+                    break;
+
+                case SIG_RSA_SHA224:
+                    hashlen = 28;
+                    break;
+
+                case SIG_RSA_SHA256:
+                    hashlen = 32;
+                    break;
+
+                case SIG_RSA_SHA384:
+                    hashlen = 48;
+                    break;
+
+                case SIG_RSA_SHA512:
+                    hashlen = 64;
+                    break;
+
+                default:
+                    return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+            }
+
+            md_info = md_info_from_type( ctx->hash_id );
+            if( md_info == NULL )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+                
+            hlen = md_get_size( md_info );
+            slen = siglen - hlen - 1;
+
+            memset( &md_ctx, 0, sizeof( md_context_t ) );
+            memset( zeros, 0, 8 );
+
+            md_init_ctx( &md_ctx, md_info );
+
+            // Note: EMSA-PSS verification is over the length of N - 1 bits
+            //
+            msb = mpi_msb( &ctx->N ) - 1;
+
+            // Compensate for boundary condition when applying mask
+            //
+            if( msb % 8 == 0 )
+            {
+                p++;
+                siglen -= 1;
+            }
+            if( buf[0] >> ( 8 - siglen * 8 + msb ) )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
+
+            buf[0] &= 0xFF >> ( siglen * 8 - msb );
+
+            while( *p == 0 && p < buf + siglen )
+                p++;
+
+            if( p == buf + siglen )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            if( *p++ != 0x01 )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            slen -= p - buf;
+
+            // Generate H = Hash( M' )
+            //
+            md_starts( &md_ctx );
+            md_update( &md_ctx, zeros, 8 );
+            md_update( &md_ctx, hash, hashlen );
+            md_update( &md_ctx, p, slen );
+            md_finish( &md_ctx, p );
+
+            if( memcmp( p, p + slen, hlen ) == 0 )
+                return( 0 );
+            else
+                return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+#endif
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    return( POLARSSL_ERR_RSA_INVALID_PADDING );
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx )
+{
+    mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
+    mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
+    mpi_free( &ctx->Q  ); mpi_free( &ctx->P  ); mpi_free( &ctx->D );
+    mpi_free( &ctx->E  ); mpi_free( &ctx->N  );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/sha1.h"
+
+/*
+ * Example RSA-1024 keypair, for test purposes
+ */
+#define KEY_LEN 128
+
+#define RSA_N   "9292758453063D803DD603D5E777D788" \
+                "8ED1D5BF35786190FA2F23EBC0848AEA" \
+                "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
+                "7130B9CED7ACDF54CFC7555AC14EEBAB" \
+                "93A89813FBF3C4F8066D2D800F7C38A8" \
+                "1AE31942917403FF4946B0A83D3D3E05" \
+                "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
+                "5E94BB77B07507233A0BC7BAC8F90F79"
+
+#define RSA_E   "10001"
+
+#define RSA_D   "24BF6185468786FDD303083D25E64EFC" \
+                "66CA472BC44D253102F8B4A9D3BFA750" \
+                "91386C0077937FE33FA3252D28855837" \
+                "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
+                "DF79C5CE07EE72C7F123142198164234" \
+                "CABB724CF78B8173B9F880FC86322407" \
+                "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
+                "071513A1E85B5DFA031F21ECAE91A34D"
+
+#define RSA_P   "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
+                "2C01CAD19EA484A87EA4377637E75500" \
+                "FCB2005C5C7DD6EC4AC023CDA285D796" \
+                "C3D9E75E1EFC42488BB4F1D13AC30A57"
+
+#define RSA_Q   "C000DF51A7C77AE8D7C7370C1FF55B69" \
+                "E211C2B9E5DB1ED0BF61D0D9899620F4" \
+                "910E4168387E3C30AA1E00C339A79508" \
+                "8452DD96A9A5EA5D9DCA68DA636032AF"
+
+#define RSA_DP  "C1ACF567564274FB07A0BBAD5D26E298" \
+                "3C94D22288ACD763FD8E5600ED4A702D" \
+                "F84198A5F06C2E72236AE490C93F07F8" \
+                "3CC559CD27BC2D1CA488811730BB5725"
+
+#define RSA_DQ  "4959CBF6F8FEF750AEE6977C155579C7" \
+                "D8AAEA56749EA28623272E4F7D0592AF" \
+                "7C1F1313CAC9471B5C523BFE592F517B" \
+                "407A1BD76C164B93DA2D32A383E58357"
+
+#define RSA_QP  "9AE7FBC99546432DF71896FC239EADAE" \
+                "F38D18D2B2F0E2DD275AA977E2BF4411" \
+                "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
+                "A74206CEC169D74BF5A8C50D6F48EA08"
+
+#define PT_LEN  24
+#define RSA_PT  "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
+                "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
+
+static int myrand( void *rng_state )
+{
+    if( rng_state != NULL )
+        rng_state  = NULL;
+
+    return( rand() );
+}
+
+/*
+ * Checkup routine
+ */
+int rsa_self_test( int verbose )
+{
+    size_t len;
+    rsa_context rsa;
+    unsigned char rsa_plaintext[PT_LEN];
+    unsigned char rsa_decrypted[PT_LEN];
+    unsigned char rsa_ciphertext[KEY_LEN];
+#if defined(POLARSSL_SHA1_C)
+    unsigned char sha1sum[20];
+#endif
+
+    rsa_init( &rsa, RSA_PKCS_V15, 0 );
+
+    rsa.len = KEY_LEN;
+    mpi_read_string( &rsa.N , 16, RSA_N  );
+    mpi_read_string( &rsa.E , 16, RSA_E  );
+    mpi_read_string( &rsa.D , 16, RSA_D  );
+    mpi_read_string( &rsa.P , 16, RSA_P  );
+    mpi_read_string( &rsa.Q , 16, RSA_Q  );
+    mpi_read_string( &rsa.DP, 16, RSA_DP );
+    mpi_read_string( &rsa.DQ, 16, RSA_DQ );
+    mpi_read_string( &rsa.QP, 16, RSA_QP );
+
+    if( verbose != 0 )
+        printf( "  RSA key validation: " );
+
+    if( rsa_check_pubkey(  &rsa ) != 0 ||
+        rsa_check_privkey( &rsa ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n  PKCS#1 encryption : " );
+
+    memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+
+    if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN,
+                           rsa_plaintext, rsa_ciphertext ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n  PKCS#1 decryption : " );
+
+    if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
+                           rsa_ciphertext, rsa_decrypted,
+                           sizeof(rsa_decrypted) ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+#if defined(POLARSSL_SHA1_C)
+    if( verbose != 0 )
+        printf( "passed\n  PKCS#1 data sign  : " );
+
+    sha1( rsa_plaintext, PT_LEN, sha1sum );
+
+    if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20,
+                        sha1sum, rsa_ciphertext ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n  PKCS#1 sig. verify: " );
+
+    if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20,
+                          sha1sum, rsa_ciphertext ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n\n" );
+#endif /* POLARSSL_SHA1_C */
+
+    rsa_free( &rsa );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 726 - 0
thirdparty/PolarSSL/library/sha1.c

@@ -0,0 +1,726 @@
+/*
+ *  FIPS-180-1 compliant SHA-1 implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SHA-1 standard was published by NIST in 1993.
+ *
+ *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+/* Note: This file has been modified by ST's MCD Application Team, to support 
+   the hardware crypto engine embedded in STM32F417xx */
+
+#include "config.h"
+
+#if defined(POLARSSL_SHA1_C)
+#include "main.h"
+#include "polarssl/sha1.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#endif
+
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */ 
+HASH_InitTypeDef SHA1_HASH_InitStructure;
+HASH_MsgDigest SHA1_MessageDigest;
+#endif /* USE_STM32F4XX_HW_CRYPTO */ 
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
+        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 3]       );       \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * SHA-1 context setup
+ */
+void sha1_starts( sha1_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+}
+
+static void sha1_process( sha1_context *ctx, const unsigned char data[64] )
+{
+    unsigned long temp, W[16], A, B, C, D, E;
+
+    GET_ULONG_BE( W[ 0], data,  0 );
+    GET_ULONG_BE( W[ 1], data,  4 );
+    GET_ULONG_BE( W[ 2], data,  8 );
+    GET_ULONG_BE( W[ 3], data, 12 );
+    GET_ULONG_BE( W[ 4], data, 16 );
+    GET_ULONG_BE( W[ 5], data, 20 );
+    GET_ULONG_BE( W[ 6], data, 24 );
+    GET_ULONG_BE( W[ 7], data, 28 );
+    GET_ULONG_BE( W[ 8], data, 32 );
+    GET_ULONG_BE( W[ 9], data, 36 );
+    GET_ULONG_BE( W[10], data, 40 );
+    GET_ULONG_BE( W[11], data, 44 );
+    GET_ULONG_BE( W[12], data, 48 );
+    GET_ULONG_BE( W[13], data, 52 );
+    GET_ULONG_BE( W[14], data, 56 );
+    GET_ULONG_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t)                                            \
+(                                                       \
+    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
+           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \
+    ( W[t & 0x0F] = S(temp,1) )                         \
+)
+
+#define P(a,b,c,d,e,x)                                  \
+{                                                       \
+    e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+    P( A, B, C, D, E, W[0]  );
+    P( E, A, B, C, D, W[1]  );
+    P( D, E, A, B, C, W[2]  );
+    P( C, D, E, A, B, W[3]  );
+    P( B, C, D, E, A, W[4]  );
+    P( A, B, C, D, E, W[5]  );
+    P( E, A, B, C, D, W[6]  );
+    P( D, E, A, B, C, W[7]  );
+    P( C, D, E, A, B, W[8]  );
+    P( B, C, D, E, A, W[9]  );
+    P( A, B, C, D, E, W[10] );
+    P( E, A, B, C, D, W[11] );
+    P( D, E, A, B, C, W[12] );
+    P( C, D, E, A, B, W[13] );
+    P( B, C, D, E, A, W[14] );
+    P( A, B, C, D, E, W[15] );
+    P( E, A, B, C, D, R(16) );
+    P( D, E, A, B, C, R(17) );
+    P( C, D, E, A, B, R(18) );
+    P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+    P( A, B, C, D, E, R(20) );
+    P( E, A, B, C, D, R(21) );
+    P( D, E, A, B, C, R(22) );
+    P( C, D, E, A, B, R(23) );
+    P( B, C, D, E, A, R(24) );
+    P( A, B, C, D, E, R(25) );
+    P( E, A, B, C, D, R(26) );
+    P( D, E, A, B, C, R(27) );
+    P( C, D, E, A, B, R(28) );
+    P( B, C, D, E, A, R(29) );
+    P( A, B, C, D, E, R(30) );
+    P( E, A, B, C, D, R(31) );
+    P( D, E, A, B, C, R(32) );
+    P( C, D, E, A, B, R(33) );
+    P( B, C, D, E, A, R(34) );
+    P( A, B, C, D, E, R(35) );
+    P( E, A, B, C, D, R(36) );
+    P( D, E, A, B, C, R(37) );
+    P( C, D, E, A, B, R(38) );
+    P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+    P( A, B, C, D, E, R(40) );
+    P( E, A, B, C, D, R(41) );
+    P( D, E, A, B, C, R(42) );
+    P( C, D, E, A, B, R(43) );
+    P( B, C, D, E, A, R(44) );
+    P( A, B, C, D, E, R(45) );
+    P( E, A, B, C, D, R(46) );
+    P( D, E, A, B, C, R(47) );
+    P( C, D, E, A, B, R(48) );
+    P( B, C, D, E, A, R(49) );
+    P( A, B, C, D, E, R(50) );
+    P( E, A, B, C, D, R(51) );
+    P( D, E, A, B, C, R(52) );
+    P( C, D, E, A, B, R(53) );
+    P( B, C, D, E, A, R(54) );
+    P( A, B, C, D, E, R(55) );
+    P( E, A, B, C, D, R(56) );
+    P( D, E, A, B, C, R(57) );
+    P( C, D, E, A, B, R(58) );
+    P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+    P( A, B, C, D, E, R(60) );
+    P( E, A, B, C, D, R(61) );
+    P( D, E, A, B, C, R(62) );
+    P( C, D, E, A, B, R(63) );
+    P( B, C, D, E, A, R(64) );
+    P( A, B, C, D, E, R(65) );
+    P( E, A, B, C, D, R(66) );
+    P( D, E, A, B, C, R(67) );
+    P( C, D, E, A, B, R(68) );
+    P( B, C, D, E, A, R(69) );
+    P( A, B, C, D, E, R(70) );
+    P( E, A, B, C, D, R(71) );
+    P( D, E, A, B, C, R(72) );
+    P( C, D, E, A, B, R(73) );
+    P( B, C, D, E, A, R(74) );
+    P( A, B, C, D, E, R(75) );
+    P( E, A, B, C, D, R(76) );
+    P( D, E, A, B, C, R(77) );
+    P( C, D, E, A, B, R(78) );
+    P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    unsigned long left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (unsigned long) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (unsigned long) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        sha1_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        sha1_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, ilen );
+    }
+}
+
+static const unsigned char sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] )
+{
+    unsigned long last, padn;
+    unsigned long high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_ULONG_BE( high, msglen, 0 );
+    PUT_ULONG_BE( low,  msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    sha1_update( ctx, (unsigned char *) sha1_padding, padn );
+    sha1_update( ctx, msglen, 8 );
+
+    PUT_ULONG_BE( ctx->state[0], output,  0 );
+    PUT_ULONG_BE( ctx->state[1], output,  4 );
+    PUT_ULONG_BE( ctx->state[2], output,  8 );
+    PUT_ULONG_BE( ctx->state[3], output, 12 );
+    PUT_ULONG_BE( ctx->state[4], output, 16 );
+}
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
+{
+    sha1_context ctx;
+
+    sha1_starts( &ctx );
+    sha1_update( &ctx, input, ilen );
+    sha1_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-1( file contents )
+ */
+int sha1_file( const char *path, unsigned char output[20] )
+{
+    FILE *f;
+    size_t n;
+    sha1_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( 1 );
+
+    sha1_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha1_update( &ctx, buf, n );
+
+    sha1_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha1_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( 2 );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-1 HMAC context setup
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
+{
+    size_t i;
+    unsigned char sum[20];
+
+    if( keylen > 64 )
+    {
+        sha1( key, keylen, sum );
+        keylen = 20;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-1 HMAC process buffer
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+    sha1_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-1 HMAC final digest
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
+{
+    unsigned char tmpbuf[20];
+
+    sha1_finish( ctx, tmpbuf );
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->opad, 64 );
+    sha1_update( ctx, tmpbuf, 20 );
+    sha1_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA1 HMAC context reset
+ */
+void sha1_hmac_reset( sha1_context *ctx )
+{
+    sha1_starts( ctx );
+    sha1_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-1( hmac key, input buffer )
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[20] )
+{
+#ifdef USE_STM32F4XX_HW_CRYPTO /* use HW Crypto */
+  __IO uint16_t nbvalidbitsdata = 0;
+  __IO uint16_t nbvalidbitskey = 0;
+  uint32_t i = 0;
+   
+  /* Number of valid bits in last word of the input data */
+  nbvalidbitsdata = 8 * (ilen % 4);
+
+  /* Number of valid bits in last word of the Key */
+  nbvalidbitskey = 8 * (keylen % 4);
+   
+  /* HASH IP initialization */
+  HASH_DeInit();
+
+  /* HASH Configuration */
+  HASH_StructInit(&SHA1_HASH_InitStructure);
+  SHA1_HASH_InitStructure.HASH_AlgoSelection = HASH_AlgoSelection_SHA1;
+  SHA1_HASH_InitStructure.HASH_AlgoMode = HASH_AlgoMode_HMAC;
+  SHA1_HASH_InitStructure.HASH_DataType = HASH_DataType_8b;
+  if(keylen > 64)
+  {
+    /* HMAC long key */
+    SHA1_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_LongKey;
+  }
+  else
+  {
+    /* HMAC short key */
+    SHA1_HASH_InitStructure.HASH_HMACKeyType = HASH_HMACKeyType_ShortKey;
+  }
+  HASH_Init(&SHA1_HASH_InitStructure);
+   
+  /* Configure the number of valid bits in last word of the key */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+  /* Write the Key */
+  for(i = 0; i < keylen; i++)
+  {
+    HASH_DataIn(*(uint32_t*)&key[i]);
+    i = i + 3;
+  }
+
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET);
+  
+  /* Configure the number of valid bits in last word of the input data */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitsdata);
+
+  /* Write the input block in the IN FIFO */
+  for(i = 0; i < ilen; i++)
+  {
+    HASH_DataIn(*(uint32_t*)&input[i]);
+    i = i + 3;
+  }
+
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET);  
+
+  /* Configure the number of valid bits in last word of the key */
+  HASH_SetLastWordValidBitsNbr(nbvalidbitskey);
+
+  /* Write the Key */
+  for(i = 0; i < keylen; i++)
+  {
+    HASH_DataIn(*(uint32_t*)&key[i]);
+    i = i + 3;
+  }
+
+  /* Start the HASH processor */
+  HASH_StartDigest();
+
+  /* wait until the Busy flag is RESET */
+  while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET);
+
+  /* Read the message digest */
+  HASH_GetDigest(&SHA1_MessageDigest);
+  *(uint32_t*)&output[0] = __REV(SHA1_MessageDigest.Data[0]);
+  *(uint32_t*)&output[4] = __REV(SHA1_MessageDigest.Data[1]);
+  *(uint32_t*)&output[8] = __REV(SHA1_MessageDigest.Data[2]);
+  *(uint32_t*)&output[12] = __REV(SHA1_MessageDigest.Data[3]);
+  *(uint32_t*)&output[16] = __REV(SHA1_MessageDigest.Data[4]);
+
+#else /* use SW Crypto */
+    sha1_context ctx;
+
+    sha1_hmac_starts( &ctx, key, keylen );
+    sha1_hmac_update( &ctx, input, ilen );
+    sha1_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha1_context ) );
+#endif /* USE_STM32F4XX_HW_CRYPTO */     
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static unsigned char sha1_test_buf[3][57] = 
+{
+    { "abc" },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+    { "" }
+};
+
+static const int sha1_test_buflen[3] =
+{
+    3, 56, 1000
+};
+
+static const unsigned char sha1_test_sum[3][20] =
+{
+    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+      0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+      0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+      0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char sha1_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+      "\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+      "\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+      "\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 80 times */
+    { "" }
+};
+
+static const int sha1_hmac_test_keylen[7] =
+{
+    20, 4, 20, 25, 20, 80, 80
+};
+
+static unsigned char sha1_hmac_test_buf[7][74] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "Test Using Larger Than Block-Size Key and Larger"
+      " Than One Block-Size Data" }
+};
+
+static const int sha1_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char sha1_hmac_test_sum[7][20] =
+{
+    { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
+      0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
+    { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
+      0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
+    { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
+      0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
+    { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
+      0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
+    { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
+      0x7B, 0xE1 },
+    { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
+      0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
+    { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
+      0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( int verbose )
+{
+    int i, j, buflen;
+    unsigned char buf[1024];
+    unsigned char sha1sum[20];
+    sha1_context ctx;
+
+    /*
+     * SHA-1
+     */
+    for( i = 0; i < 3; i++ )
+    {
+        if( verbose != 0 )
+            printf( "  SHA-1 test #%d: ", i + 1 );
+
+        sha1_starts( &ctx );
+
+        if( i == 2 )
+        {
+            memset( buf, 'a', buflen = 1000 );
+
+            for( j = 0; j < 1000; j++ )
+                sha1_update( &ctx, buf, buflen );
+        }
+        else
+            sha1_update( &ctx, sha1_test_buf[i],
+                               sha1_test_buflen[i] );
+
+        sha1_finish( &ctx, sha1sum );
+
+        if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    for( i = 0; i < 7; i++ )
+    {
+        if( verbose != 0 )
+            printf( "  HMAC-SHA-1 test #%d: ", i + 1 );
+
+        if( i == 5 || i == 6 )
+        {
+            memset( buf, '\xAA', buflen = 80 );
+            sha1_hmac_starts( &ctx, buf, buflen );
+        }
+        else
+            sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
+                                    sha1_hmac_test_keylen[i] );
+
+        sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
+                                sha1_hmac_test_buflen[i] );
+
+        sha1_hmac_finish( &ctx, sha1sum );
+
+        buflen = ( i == 4 ) ? 12 : 20;
+
+        if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 710 - 0
thirdparty/PolarSSL/library/sha2.c

@@ -0,0 +1,710 @@
+/*
+ *  FIPS-180-2 compliant SHA-256 implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
+ *
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_SHA2_C)
+
+#include "polarssl/sha2.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#endif
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
+        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 3]       );       \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * SHA-256 context setup
+ */
+void sha2_starts( sha2_context *ctx, int is224 )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    if( is224 == 0 )
+    {
+        /* SHA-256 */
+        ctx->state[0] = 0x6A09E667;
+        ctx->state[1] = 0xBB67AE85;
+        ctx->state[2] = 0x3C6EF372;
+        ctx->state[3] = 0xA54FF53A;
+        ctx->state[4] = 0x510E527F;
+        ctx->state[5] = 0x9B05688C;
+        ctx->state[6] = 0x1F83D9AB;
+        ctx->state[7] = 0x5BE0CD19;
+    }
+    else
+    {
+        /* SHA-224 */
+        ctx->state[0] = 0xC1059ED8;
+        ctx->state[1] = 0x367CD507;
+        ctx->state[2] = 0x3070DD17;
+        ctx->state[3] = 0xF70E5939;
+        ctx->state[4] = 0xFFC00B31;
+        ctx->state[5] = 0x68581511;
+        ctx->state[6] = 0x64F98FA7;
+        ctx->state[7] = 0xBEFA4FA4;
+    }
+
+    ctx->is224 = is224;
+}
+
+static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
+{
+    unsigned long temp1, temp2, W[64];
+    unsigned long A, B, C, D, E, F, G, H;
+
+    GET_ULONG_BE( W[ 0], data,  0 );
+    GET_ULONG_BE( W[ 1], data,  4 );
+    GET_ULONG_BE( W[ 2], data,  8 );
+    GET_ULONG_BE( W[ 3], data, 12 );
+    GET_ULONG_BE( W[ 4], data, 16 );
+    GET_ULONG_BE( W[ 5], data, 20 );
+    GET_ULONG_BE( W[ 6], data, 24 );
+    GET_ULONG_BE( W[ 7], data, 28 );
+    GET_ULONG_BE( W[ 8], data, 32 );
+    GET_ULONG_BE( W[ 9], data, 36 );
+    GET_ULONG_BE( W[10], data, 40 );
+    GET_ULONG_BE( W[11], data, 44 );
+    GET_ULONG_BE( W[12], data, 48 );
+    GET_ULONG_BE( W[13], data, 52 );
+    GET_ULONG_BE( W[14], data, 56 );
+    GET_ULONG_BE( W[15], data, 60 );
+
+#define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t)                                    \
+(                                               \
+    W[t] = S1(W[t -  2]) + W[t -  7] +          \
+           S0(W[t - 15]) + W[t - 16]            \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K)                  \
+{                                               \
+    temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
+    temp2 = S2(a) + F0(a,b,c);                  \
+    d += temp1; h = temp1 + temp2;              \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+    F = ctx->state[5];
+    G = ctx->state[6];
+    H = ctx->state[7];
+
+    P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
+    P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
+    P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
+    P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
+    P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
+    P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
+    P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
+    P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
+    P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
+    P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
+    P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
+    P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
+    P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
+    P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
+    P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
+    P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
+    P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
+    P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
+    P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
+    P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
+    P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
+    P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
+    P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
+    P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
+    P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
+    P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
+    P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
+    P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
+    P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
+    P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
+    P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
+    P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
+    P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
+    P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
+    P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
+    P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
+    P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
+    P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
+    P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
+    P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
+    P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
+    P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
+    P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
+    P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
+    P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
+    P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
+    P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
+    P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
+    P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
+    P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
+    P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
+    P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
+    P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
+    P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
+    P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
+    P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
+    P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
+    P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
+    P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
+    P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
+    P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
+    P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
+    P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
+    P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+    ctx->state[5] += F;
+    ctx->state[6] += G;
+    ctx->state[7] += H;
+}
+
+/*
+ * SHA-256 process buffer
+ */
+void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    unsigned long left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (unsigned long) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (unsigned long) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        sha2_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        sha2_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, ilen );
+    }
+}
+
+static const unsigned char sha2_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-256 final digest
+ */
+void sha2_finish( sha2_context *ctx, unsigned char output[32] )
+{
+    unsigned long last, padn;
+    unsigned long high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_ULONG_BE( high, msglen, 0 );
+    PUT_ULONG_BE( low,  msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    sha2_update( ctx, (unsigned char *) sha2_padding, padn );
+    sha2_update( ctx, msglen, 8 );
+
+    PUT_ULONG_BE( ctx->state[0], output,  0 );
+    PUT_ULONG_BE( ctx->state[1], output,  4 );
+    PUT_ULONG_BE( ctx->state[2], output,  8 );
+    PUT_ULONG_BE( ctx->state[3], output, 12 );
+    PUT_ULONG_BE( ctx->state[4], output, 16 );
+    PUT_ULONG_BE( ctx->state[5], output, 20 );
+    PUT_ULONG_BE( ctx->state[6], output, 24 );
+
+    if( ctx->is224 == 0 )
+        PUT_ULONG_BE( ctx->state[7], output, 28 );
+}
+
+/*
+ * output = SHA-256( input buffer )
+ */
+void sha2( const unsigned char *input, size_t ilen,
+           unsigned char output[32], int is224 )
+{
+    sha2_context ctx;
+
+    sha2_starts( &ctx, is224 );
+    sha2_update( &ctx, input, ilen );
+    sha2_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha2_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-256( file contents )
+ */
+int sha2_file( const char *path, unsigned char output[32], int is224 )
+{
+    FILE *f;
+    size_t n;
+    sha2_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( 1 );
+
+    sha2_starts( &ctx, is224 );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha2_update( &ctx, buf, n );
+
+    sha2_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha2_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( 2 );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-256 HMAC context setup
+ */
+void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
+                       int is224 )
+{
+    size_t i;
+    unsigned char sum[32];
+
+    if( keylen > 64 )
+    {
+        sha2( key, keylen, sum, is224 );
+        keylen = ( is224 ) ? 28 : 32;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sha2_starts( ctx, is224 );
+    sha2_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-256 HMAC process buffer
+ */
+void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
+{
+    sha2_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-256 HMAC final digest
+ */
+void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
+{
+    int is224, hlen;
+    unsigned char tmpbuf[32];
+
+    is224 = ctx->is224;
+    hlen = ( is224 == 0 ) ? 32 : 28;
+
+    sha2_finish( ctx, tmpbuf );
+    sha2_starts( ctx, is224 );
+    sha2_update( ctx, ctx->opad, 64 );
+    sha2_update( ctx, tmpbuf, hlen );
+    sha2_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-256 HMAC context reset
+ */
+void sha2_hmac_reset( sha2_context *ctx )
+{
+    sha2_starts( ctx, ctx->is224 );
+    sha2_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-256( hmac key, input buffer )
+ */
+void sha2_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[32], int is224 )
+{
+    sha2_context ctx;
+
+    sha2_hmac_starts( &ctx, key, keylen, is224 );
+    sha2_hmac_update( &ctx, input, ilen );
+    sha2_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha2_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha2_test_buf[3][57] = 
+{
+    { "abc" },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+    { "" }
+};
+
+static const int sha2_test_buflen[3] =
+{
+    3, 56, 1000
+};
+
+static const unsigned char sha2_test_sum[6][32] =
+{
+    /*
+     * SHA-224 test vectors
+     */
+    { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+      0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+      0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+      0xE3, 0x6C, 0x9D, 0xA7 },
+    { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+      0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+      0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+      0x52, 0x52, 0x25, 0x25 },
+    { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
+      0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
+      0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
+      0x4E, 0xE7, 0xAD, 0x67 },
+
+    /*
+     * SHA-256 test vectors
+     */
+    { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+      0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+      0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+      0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
+    { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+      0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+      0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+      0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
+    { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+      0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+      0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+      0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha2_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+      "\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+      "\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+      "\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 131 times */
+    { "" }
+};
+
+static const int sha2_hmac_test_keylen[7] =
+{
+    20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha2_hmac_test_buf[7][153] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "This is a test using a larger than block-size key "
+      "and a larger than block-size data. The key needs to "
+      "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha2_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha2_hmac_test_sum[14][32] =
+{
+    /*
+     * HMAC-SHA-224 test vectors
+     */
+    { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
+      0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
+      0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
+      0x53, 0x68, 0x4B, 0x22 },
+    { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
+      0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
+      0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
+      0x8F, 0xD0, 0x5E, 0x44 },
+    { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
+      0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
+      0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
+      0xEC, 0x83, 0x33, 0xEA },
+    { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
+      0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
+      0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
+      0xE7, 0xAF, 0xEC, 0x5A },
+    { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
+      0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
+    { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
+      0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
+      0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
+      0x3F, 0xA6, 0x87, 0x0E },
+    { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
+      0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
+      0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
+      0xF6, 0xF5, 0x65, 0xD1 },
+
+    /*
+     * HMAC-SHA-256 test vectors
+     */
+    { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
+      0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
+      0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
+      0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
+    { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
+      0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
+      0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
+      0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
+    { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
+      0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
+      0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
+      0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
+    { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
+      0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
+      0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
+      0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
+    { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
+      0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
+    { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
+      0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
+      0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
+      0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
+    { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
+      0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
+      0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
+      0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha2_self_test( int verbose )
+{
+    int i, j, k, buflen;
+    unsigned char buf[1024];
+    unsigned char sha2sum[32];
+    sha2_context ctx;
+
+    for( i = 0; i < 6; i++ )
+    {
+        j = i % 3;
+        k = i < 3;
+
+        if( verbose != 0 )
+            printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+        sha2_starts( &ctx, k );
+
+        if( j == 2 )
+        {
+            memset( buf, 'a', buflen = 1000 );
+
+            for( j = 0; j < 1000; j++ )
+                sha2_update( &ctx, buf, buflen );
+        }
+        else
+            sha2_update( &ctx, sha2_test_buf[j],
+                               sha2_test_buflen[j] );
+
+        sha2_finish( &ctx, sha2sum );
+
+        if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    for( i = 0; i < 14; i++ )
+    {
+        j = i % 7;
+        k = i < 7;
+
+        if( verbose != 0 )
+            printf( "  HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+        if( j == 5 || j == 6 )
+        {
+            memset( buf, '\xAA', buflen = 131 );
+            sha2_hmac_starts( &ctx, buf, buflen, k );
+        }
+        else
+            sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
+                                    sha2_hmac_test_keylen[j], k );
+
+        sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
+                                sha2_hmac_test_buflen[j] );
+
+        sha2_hmac_finish( &ctx, sha2sum );
+
+        buflen = ( j == 4 ) ? 16 : 32 - k * 4;
+
+        if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 765 - 0
thirdparty/PolarSSL/library/sha4.c

@@ -0,0 +1,765 @@
+/*
+ *  FIPS-180-2 compliant SHA-384/512 implementation
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SHA-512 Secure Hash Standard was published by NIST in 2002.
+ *
+ *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_SHA4_C)
+
+#include "polarssl/sha4.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#endif
+
+/*
+ * 64-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT64_BE
+#define GET_UINT64_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (unsigned int64) (b)[(i)    ] << 56 )       \
+        | ( (unsigned int64) (b)[(i) + 1] << 48 )       \
+        | ( (unsigned int64) (b)[(i) + 2] << 40 )       \
+        | ( (unsigned int64) (b)[(i) + 3] << 32 )       \
+        | ( (unsigned int64) (b)[(i) + 4] << 24 )       \
+        | ( (unsigned int64) (b)[(i) + 5] << 16 )       \
+        | ( (unsigned int64) (b)[(i) + 6] <<  8 )       \
+        | ( (unsigned int64) (b)[(i) + 7]       );      \
+}
+#endif
+
+#ifndef PUT_UINT64_BE
+#define PUT_UINT64_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 56 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 48 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 40 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 32 );       \
+    (b)[(i) + 4] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 5] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 6] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 7] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * Round constants
+ */
+static const unsigned int64 K[80] =
+{
+    UL64(0x428A2F98D728AE22),  UL64(0x7137449123EF65CD),
+    UL64(0xB5C0FBCFEC4D3B2F),  UL64(0xE9B5DBA58189DBBC),
+    UL64(0x3956C25BF348B538),  UL64(0x59F111F1B605D019),
+    UL64(0x923F82A4AF194F9B),  UL64(0xAB1C5ED5DA6D8118),
+    UL64(0xD807AA98A3030242),  UL64(0x12835B0145706FBE),
+    UL64(0x243185BE4EE4B28C),  UL64(0x550C7DC3D5FFB4E2),
+    UL64(0x72BE5D74F27B896F),  UL64(0x80DEB1FE3B1696B1),
+    UL64(0x9BDC06A725C71235),  UL64(0xC19BF174CF692694),
+    UL64(0xE49B69C19EF14AD2),  UL64(0xEFBE4786384F25E3),
+    UL64(0x0FC19DC68B8CD5B5),  UL64(0x240CA1CC77AC9C65),
+    UL64(0x2DE92C6F592B0275),  UL64(0x4A7484AA6EA6E483),
+    UL64(0x5CB0A9DCBD41FBD4),  UL64(0x76F988DA831153B5),
+    UL64(0x983E5152EE66DFAB),  UL64(0xA831C66D2DB43210),
+    UL64(0xB00327C898FB213F),  UL64(0xBF597FC7BEEF0EE4),
+    UL64(0xC6E00BF33DA88FC2),  UL64(0xD5A79147930AA725),
+    UL64(0x06CA6351E003826F),  UL64(0x142929670A0E6E70),
+    UL64(0x27B70A8546D22FFC),  UL64(0x2E1B21385C26C926),
+    UL64(0x4D2C6DFC5AC42AED),  UL64(0x53380D139D95B3DF),
+    UL64(0x650A73548BAF63DE),  UL64(0x766A0ABB3C77B2A8),
+    UL64(0x81C2C92E47EDAEE6),  UL64(0x92722C851482353B),
+    UL64(0xA2BFE8A14CF10364),  UL64(0xA81A664BBC423001),
+    UL64(0xC24B8B70D0F89791),  UL64(0xC76C51A30654BE30),
+    UL64(0xD192E819D6EF5218),  UL64(0xD69906245565A910),
+    UL64(0xF40E35855771202A),  UL64(0x106AA07032BBD1B8),
+    UL64(0x19A4C116B8D2D0C8),  UL64(0x1E376C085141AB53),
+    UL64(0x2748774CDF8EEB99),  UL64(0x34B0BCB5E19B48A8),
+    UL64(0x391C0CB3C5C95A63),  UL64(0x4ED8AA4AE3418ACB),
+    UL64(0x5B9CCA4F7763E373),  UL64(0x682E6FF3D6B2B8A3),
+    UL64(0x748F82EE5DEFB2FC),  UL64(0x78A5636F43172F60),
+    UL64(0x84C87814A1F0AB72),  UL64(0x8CC702081A6439EC),
+    UL64(0x90BEFFFA23631E28),  UL64(0xA4506CEBDE82BDE9),
+    UL64(0xBEF9A3F7B2C67915),  UL64(0xC67178F2E372532B),
+    UL64(0xCA273ECEEA26619C),  UL64(0xD186B8C721C0C207),
+    UL64(0xEADA7DD6CDE0EB1E),  UL64(0xF57D4F7FEE6ED178),
+    UL64(0x06F067AA72176FBA),  UL64(0x0A637DC5A2C898A6),
+    UL64(0x113F9804BEF90DAE),  UL64(0x1B710B35131C471B),
+    UL64(0x28DB77F523047D84),  UL64(0x32CAAB7B40C72493),
+    UL64(0x3C9EBE0A15C9BEBC),  UL64(0x431D67C49C100D4C),
+    UL64(0x4CC5D4BECB3E42B6),  UL64(0x597F299CFC657E2A),
+    UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)
+};
+
+/*
+ * SHA-512 context setup
+ */
+void sha4_starts( sha4_context *ctx, int is384 )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    if( is384 == 0 )
+    {
+        /* SHA-512 */
+        ctx->state[0] = UL64(0x6A09E667F3BCC908);
+        ctx->state[1] = UL64(0xBB67AE8584CAA73B);
+        ctx->state[2] = UL64(0x3C6EF372FE94F82B);
+        ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
+        ctx->state[4] = UL64(0x510E527FADE682D1);
+        ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
+        ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
+        ctx->state[7] = UL64(0x5BE0CD19137E2179);
+    }
+    else
+    {
+        /* SHA-384 */
+        ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
+        ctx->state[1] = UL64(0x629A292A367CD507);
+        ctx->state[2] = UL64(0x9159015A3070DD17);
+        ctx->state[3] = UL64(0x152FECD8F70E5939);
+        ctx->state[4] = UL64(0x67332667FFC00B31);
+        ctx->state[5] = UL64(0x8EB44A8768581511);
+        ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
+        ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
+    }
+
+    ctx->is384 = is384;
+}
+
+static void sha4_process( sha4_context *ctx, const unsigned char data[128] )
+{
+    int i;
+    unsigned int64 temp1, temp2, W[80];
+    unsigned int64 A, B, C, D, E, F, G, H;
+
+#define  SHR(x,n) (x >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
+
+#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^  SHR(x, 7))
+#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^  SHR(x, 6))
+
+#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
+#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define P(a,b,c,d,e,f,g,h,x,K)                  \
+{                                               \
+    temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
+    temp2 = S2(a) + F0(a,b,c);                  \
+    d += temp1; h = temp1 + temp2;              \
+}
+
+    for( i = 0; i < 16; i++ )
+    {
+        GET_UINT64_BE( W[i], data, i << 3 );
+    }
+
+    for( ; i < 80; i++ )
+    {
+        W[i] = S1(W[i -  2]) + W[i -  7] +
+               S0(W[i - 15]) + W[i - 16];
+    }
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+    F = ctx->state[5];
+    G = ctx->state[6];
+    H = ctx->state[7];
+    i = 0;
+
+    do
+    {
+        P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
+        P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
+        P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
+        P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
+        P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
+        P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
+        P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
+        P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
+    }
+    while( i < 80 );
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+    ctx->state[4] += E;
+    ctx->state[5] += F;
+    ctx->state[6] += G;
+    ctx->state[7] += H;
+}
+
+/*
+ * SHA-512 process buffer
+ */
+void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    unsigned int left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = (unsigned int) (ctx->total[0] & 0x7F);
+    fill = 128 - left;
+
+    ctx->total[0] += (unsigned int64) ilen;
+
+    if( ctx->total[0] < (unsigned int64) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        sha4_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 128 )
+    {
+        sha4_process( ctx, input );
+        input += 128;
+        ilen  -= 128;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, ilen );
+    }
+}
+
+static const unsigned char sha4_padding[128] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-512 final digest
+ */
+void sha4_finish( sha4_context *ctx, unsigned char output[64] )
+{
+    size_t last, padn;
+    unsigned int64 high, low;
+    unsigned char msglen[16];
+
+    high = ( ctx->total[0] >> 61 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT64_BE( high, msglen, 0 );
+    PUT_UINT64_BE( low,  msglen, 8 );
+
+    last = (size_t)( ctx->total[0] & 0x7F );
+    padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
+
+    sha4_update( ctx, (unsigned char *) sha4_padding, padn );
+    sha4_update( ctx, msglen, 16 );
+
+    PUT_UINT64_BE( ctx->state[0], output,  0 );
+    PUT_UINT64_BE( ctx->state[1], output,  8 );
+    PUT_UINT64_BE( ctx->state[2], output, 16 );
+    PUT_UINT64_BE( ctx->state[3], output, 24 );
+    PUT_UINT64_BE( ctx->state[4], output, 32 );
+    PUT_UINT64_BE( ctx->state[5], output, 40 );
+
+    if( ctx->is384 == 0 )
+    {
+        PUT_UINT64_BE( ctx->state[6], output, 48 );
+        PUT_UINT64_BE( ctx->state[7], output, 56 );
+    }
+}
+
+/*
+ * output = SHA-512( input buffer )
+ */
+void sha4( const unsigned char *input, size_t ilen,
+           unsigned char output[64], int is384 )
+{
+    sha4_context ctx;
+
+    sha4_starts( &ctx, is384 );
+    sha4_update( &ctx, input, ilen );
+    sha4_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha4_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-512( file contents )
+ */
+int sha4_file( const char *path, unsigned char output[64], int is384 )
+{
+    FILE *f;
+    size_t n;
+    sha4_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( 1 );
+
+    sha4_starts( &ctx, is384 );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sha4_update( &ctx, buf, n );
+
+    sha4_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha4_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( 2 );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-512 HMAC context setup
+ */
+void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
+                       int is384 )
+{
+    size_t i;
+    unsigned char sum[64];
+
+    if( keylen > 128 )
+    {
+        sha4( key, keylen, sum, is384 );
+        keylen = ( is384 ) ? 48 : 64;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 128 );
+    memset( ctx->opad, 0x5C, 128 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sha4_starts( ctx, is384 );
+    sha4_update( ctx, ctx->ipad, 128 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-512 HMAC process buffer
+ */
+void sha4_hmac_update( sha4_context  *ctx,
+                       const unsigned char *input, size_t ilen )
+{
+    sha4_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-512 HMAC final digest
+ */
+void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] )
+{
+    int is384, hlen;
+    unsigned char tmpbuf[64];
+
+    is384 = ctx->is384;
+    hlen = ( is384 == 0 ) ? 64 : 48;
+
+    sha4_finish( ctx, tmpbuf );
+    sha4_starts( ctx, is384 );
+    sha4_update( ctx, ctx->opad, 128 );
+    sha4_update( ctx, tmpbuf, hlen );
+    sha4_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-512 HMAC context reset
+ */
+void sha4_hmac_reset( sha4_context *ctx )
+{
+    sha4_starts( ctx, ctx->is384 );
+    sha4_update( ctx, ctx->ipad, 128 );
+}
+
+/*
+ * output = HMAC-SHA-512( hmac key, input buffer )
+ */
+void sha4_hmac( const unsigned char *key, size_t keylen,
+                const unsigned char *input, size_t ilen,
+                unsigned char output[64], int is384 )
+{
+    sha4_context ctx;
+
+    sha4_hmac_starts( &ctx, key, keylen, is384 );
+    sha4_hmac_update( &ctx, input, ilen );
+    sha4_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sha4_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha4_test_buf[3][113] = 
+{
+    { "abc" },
+    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+      "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+    { "" }
+};
+
+static const int sha4_test_buflen[3] =
+{
+    3, 112, 1000
+};
+
+static const unsigned char sha4_test_sum[6][64] =
+{
+    /*
+     * SHA-384 test vectors
+     */
+    { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
+      0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
+      0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
+      0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
+      0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
+      0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
+    { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
+      0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
+      0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
+      0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
+      0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
+      0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
+    { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
+      0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
+      0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
+      0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
+      0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
+      0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
+
+    /*
+     * SHA-512 test vectors
+     */
+    { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
+      0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
+      0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+      0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
+      0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
+      0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+      0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
+      0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
+    { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
+      0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
+      0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
+      0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
+      0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
+      0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
+      0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
+      0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
+    { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
+      0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
+      0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
+      0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
+      0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
+      0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
+      0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
+      0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha4_hmac_test_key[7][26] =
+{
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+      "\x0B\x0B\x0B\x0B" },
+    { "Jefe" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+      "\xAA\xAA\xAA\xAA" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+      "\x0C\x0C\x0C\x0C" },
+    { "" }, /* 0xAA 131 times */
+    { "" }
+};
+
+static const int sha4_hmac_test_keylen[7] =
+{
+    20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha4_hmac_test_buf[7][153] =
+{
+    { "Hi There" },
+    { "what do ya want for nothing?" },
+    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+    { "Test With Truncation" },
+    { "Test Using Larger Than Block-Size Key - Hash Key First" },
+    { "This is a test using a larger than block-size key "
+      "and a larger than block-size data. The key needs to "
+      "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha4_hmac_test_buflen[7] =
+{
+    8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha4_hmac_test_sum[14][64] =
+{
+    /*
+     * HMAC-SHA-384 test vectors
+     */
+    { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62,
+      0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F,
+      0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6,
+      0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C,
+      0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F,
+      0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 },
+    { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31,
+      0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B,
+      0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47,
+      0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E,
+      0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7,
+      0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 },
+    { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A,
+      0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F,
+      0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB,
+      0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B,
+      0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9,
+      0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 },
+    { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85,
+      0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7,
+      0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C,
+      0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E,
+      0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79,
+      0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB },
+    { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23,
+      0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 },
+    { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90,
+      0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4,
+      0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F,
+      0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6,
+      0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82,
+      0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 },
+    { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D,
+      0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C,
+      0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A,
+      0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5,
+      0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D,
+      0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E },
+
+    /*
+     * HMAC-SHA-512 test vectors
+     */
+    { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D,
+      0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0,
+      0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78,
+      0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE,
+      0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02,
+      0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4,
+      0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70,
+      0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 },
+    { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2,
+      0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3,
+      0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6,
+      0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54,
+      0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A,
+      0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD,
+      0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B,
+      0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 },
+    { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84,
+      0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9,
+      0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36,
+      0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39,
+      0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8,
+      0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07,
+      0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26,
+      0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB },
+    { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69,
+      0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7,
+      0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D,
+      0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB,
+      0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4,
+      0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63,
+      0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D,
+      0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD },
+    { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53,
+      0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 },
+    { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB,
+      0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4,
+      0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1,
+      0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52,
+      0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98,
+      0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52,
+      0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC,
+      0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 },
+    { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA,
+      0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD,
+      0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86,
+      0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44,
+      0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1,
+      0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15,
+      0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60,
+      0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha4_self_test( int verbose )
+{
+    int i, j, k, buflen;
+    unsigned char buf[1024];
+    unsigned char sha4sum[64];
+    sha4_context ctx;
+
+    for( i = 0; i < 6; i++ )
+    {
+        j = i % 3;
+        k = i < 3;
+
+        if( verbose != 0 )
+            printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+        sha4_starts( &ctx, k );
+
+        if( j == 2 )
+        {
+            memset( buf, 'a', buflen = 1000 );
+
+            for( j = 0; j < 1000; j++ )
+                sha4_update( &ctx, buf, buflen );
+        }
+        else
+            sha4_update( &ctx, sha4_test_buf[j],
+                               sha4_test_buflen[j] );
+
+        sha4_finish( &ctx, sha4sum );
+
+        if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    for( i = 0; i < 14; i++ )
+    {
+        j = i % 7;
+        k = i < 7;
+
+        if( verbose != 0 )
+            printf( "  HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+        if( j == 5 || j == 6 )
+        {
+            memset( buf, '\xAA', buflen = 131 );
+            sha4_hmac_starts( &ctx, buf, buflen, k );
+        }
+        else
+            sha4_hmac_starts( &ctx, sha4_hmac_test_key[j],
+                                    sha4_hmac_test_keylen[j], k );
+
+        sha4_hmac_update( &ctx, sha4_hmac_test_buf[j],
+                                sha4_hmac_test_buflen[j] );
+
+        sha4_hmac_finish( &ctx, sha4sum );
+
+        buflen = ( j == 4 ) ? 16 : 64 - k * 16;
+
+        if( memcmp( sha4sum, sha4_hmac_test_sum[i], buflen ) != 0 )
+        {
+            if( verbose != 0 )
+                printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( 0 );
+}
+
+#endif
+
+#endif

+ 828 - 0
thirdparty/PolarSSL/library/ssl_cli.c

@@ -0,0 +1,828 @@
+/*
+ *  SSLv3/TLSv1 client-side functions
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_SSL_CLI_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_PKCS11_C)
+#include "polarssl/pkcs11.h"
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+#include <stdlib.h>
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#include <time.h>
+
+static int ssl_write_client_hello( ssl_context *ssl )
+{
+    int ret;
+    size_t i, n;
+    unsigned char *buf;
+    unsigned char *p;
+    time_t t;
+
+    SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
+
+    ssl->major_ver = SSL_MAJOR_VERSION_3;
+    ssl->minor_ver = SSL_MINOR_VERSION_0;
+
+    ssl->max_major_ver = SSL_MAJOR_VERSION_3;
+    ssl->max_minor_ver = SSL_MINOR_VERSION_2;
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   highest version supported
+     *     6  .   9   current UNIX time
+     *    10  .  37   random bytes
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    *p++ = (unsigned char) ssl->max_major_ver;
+    *p++ = (unsigned char) ssl->max_minor_ver;
+
+    SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
+                   buf[4], buf[5] ) );
+
+    t = time( NULL );
+    *p++ = (unsigned char)( t >> 24 );
+    *p++ = (unsigned char)( t >> 16 );
+    *p++ = (unsigned char)( t >>  8 );
+    *p++ = (unsigned char)( t       );
+
+    SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
+
+    for( i = 28; i > 0; i-- )
+        *p++ = (unsigned char) ssl->f_rng( ssl->p_rng );
+
+    memcpy( ssl->randbytes, buf + 6, 32 );
+
+    SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 );
+
+    /*
+     *    38  .  38   session id length
+     *    39  . 39+n  session id
+     *   40+n . 41+n  ciphersuitelist length
+     *   42+n . ..    ciphersuitelist
+     *   ..   . ..    compression alg. (0)
+     *   ..   . ..    extensions (unused)
+     */
+    n = ssl->session->length;
+
+    if( n < 16 || n > 32 || ssl->resume == 0 ||
+        ( ssl->timeout != 0 && t - ssl->session->start > ssl->timeout ) )
+        n = 0;
+
+    *p++ = (unsigned char) n;
+
+    for( i = 0; i < n; i++ )
+        *p++ = ssl->session->id[i];
+
+    SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
+    SSL_DEBUG_BUF( 3,   "client hello, session id", buf + 39, n );
+
+    for( n = 0; ssl->ciphersuites[n] != 0; n++ );
+    *p++ = (unsigned char)( n >> 7 );
+    *p++ = (unsigned char)( n << 1 );
+
+    SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
+
+    for( i = 0; i < n; i++ )
+    {
+        SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d",
+                       ssl->ciphersuites[i] ) );
+
+        *p++ = (unsigned char)( ssl->ciphersuites[i] >> 8 );
+        *p++ = (unsigned char)( ssl->ciphersuites[i]      );
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
+    SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", 0 ) );
+
+    *p++ = 1;
+    *p++ = SSL_COMPRESS_NULL;
+
+    if ( ssl->hostname != NULL )
+    {
+        SSL_DEBUG_MSG( 3, ( "client hello, server name extension: %s",
+                       ssl->hostname ) );
+
+        *p++ = (unsigned char)( ( (ssl->hostname_len + 9) >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( (ssl->hostname_len + 9)      ) & 0xFF );
+
+        *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME      ) & 0xFF );
+
+        *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( (ssl->hostname_len + 5)      ) & 0xFF );
+
+        *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( (ssl->hostname_len + 3)      ) & 0xFF );
+
+        *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
+        *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( ssl->hostname_len      ) & 0xFF );
+
+        memcpy( p, ssl->hostname, ssl->hostname_len );
+
+        p += ssl->hostname_len;
+    }
+
+    ssl->out_msglen  = p - buf;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CLIENT_HELLO;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
+
+    return( 0 );
+}
+
+static int ssl_parse_server_hello( ssl_context *ssl )
+{
+    time_t t;
+    int ret, i;
+    size_t n;
+    int ext_len;
+    unsigned char *buf;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   protocol version
+     *     6  .   9   UNIX time()
+     *    10  .  37   random bytes
+     */
+    buf = ssl->in_msg;
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+                   buf[4], buf[5] ) );
+
+    if( ssl->in_hslen < 42 ||
+        buf[0] != SSL_HS_SERVER_HELLO ||
+        buf[4] != SSL_MAJOR_VERSION_3 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    if( buf[5] > ssl->max_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    ssl->minor_ver = buf[5];
+
+    t = ( (time_t) buf[6] << 24 )
+      | ( (time_t) buf[7] << 16 )
+      | ( (time_t) buf[8] <<  8 )
+      | ( (time_t) buf[9]       );
+
+    memcpy( ssl->randbytes + 32, buf + 6, 32 );
+
+    n = buf[38];
+
+    SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+    SSL_DEBUG_BUF( 3,   "server hello, random bytes", buf + 6, 32 );
+
+    /*
+     *    38  .  38   session id length
+     *    39  . 38+n  session id
+     *   39+n . 40+n  chosen ciphersuite
+     *   41+n . 41+n  chosen compression alg.
+     *   42+n . 43+n  extensions length
+     *   44+n . 44+n+m extensions
+     */
+    if( n > 32 || ssl->in_hslen > 42 + n )
+    {
+        ext_len = ( ( buf[42 + n] <<  8 )
+                  | ( buf[43 + n]       ) ) + 2;
+    }
+    else
+    {
+        ext_len = 0;
+    }
+
+    if( n > 32 || ssl->in_hslen != 42 + n + ext_len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    i = ( buf[39 + n] << 8 ) | buf[40 + n];
+
+    SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+    SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
+
+    /*
+     * Check if the session can be resumed
+     */
+    if( ssl->resume == 0 || n == 0 ||
+        ssl->session->ciphersuite != i ||
+        ssl->session->length != n ||
+        memcmp( ssl->session->id, buf + 39, n ) != 0 )
+    {
+        ssl->state++;
+        ssl->resume = 0;
+        ssl->session->start = time( NULL );
+        ssl->session->ciphersuite = i;
+        ssl->session->length = n;
+        memcpy( ssl->session->id, buf + 39, n );
+    }
+    else
+    {
+        ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+        if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+            return( ret );
+        }
+    }
+
+    SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+                   ssl->resume ? "a" : "no" ) );
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) );
+    SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) );
+
+    i = 0;
+    while( 1 )
+    {
+        if( ssl->ciphersuites[i] == 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+        }
+
+        if( ssl->ciphersuites[i++] == ssl->session->ciphersuite )
+            break;
+    }
+
+    if( buf[41 + n] != SSL_COMPRESS_NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    /* TODO: Process extensions */
+
+    SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
+
+    return( 0 );
+}
+
+static int ssl_parse_server_key_exchange( ssl_context *ssl )
+{
+#if defined(POLARSSL_DHM_C)
+    int ret;
+    size_t n;
+    unsigned char *p, *end;
+    unsigned char hash[36];
+    md5_context md5;
+    sha1_context sha1;
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
+
+    if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA)
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+#if !defined(POLARSSL_DHM_C)
+    SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
+    return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    /*
+     * Ephemeral DH parameters:
+     *
+     * struct {
+     *     opaque dh_p<1..2^16-1>;
+     *     opaque dh_g<1..2^16-1>;
+     *     opaque dh_Ys<1..2^16-1>;
+     * } ServerDHParams;
+     */
+    p   = ssl->in_msg + 4;
+    end = ssl->in_msg + ssl->in_hslen;
+
+    if( ( ret = dhm_read_params( &ssl->dhm_ctx, &p, end ) ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    if( (unsigned int)( end - p ) != ssl->peer_cert->rsa.len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    if( ssl->dhm_ctx.len < 64 || ssl->dhm_ctx.len > 256 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+    }
+
+    SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P  );
+    SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G  );
+    SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
+
+    /*
+     * digitally-signed struct {
+     *     opaque md5_hash[16];
+     *     opaque sha_hash[20];
+     * };
+     *
+     * md5_hash
+     *     MD5(ClientHello.random + ServerHello.random
+     *                            + ServerParams);
+     * sha_hash
+     *     SHA(ClientHello.random + ServerHello.random
+     *                            + ServerParams);
+     */
+    n = ssl->in_hslen - ( end - p ) - 6;
+
+    md5_starts( &md5 );
+    md5_update( &md5, ssl->randbytes, 64 );
+    md5_update( &md5, ssl->in_msg + 4, n );
+    md5_finish( &md5, hash );
+
+    sha1_starts( &sha1 );
+    sha1_update( &sha1, ssl->randbytes, 64 );
+    sha1_update( &sha1, ssl->in_msg + 4, n );
+    sha1_finish( &sha1, hash + 16 );
+
+    SSL_DEBUG_BUF( 3, "parameters hash", hash, 36 );
+
+    if( ( ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
+                                  SIG_RSA_RAW, 36, hash, p ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+        return( ret );
+    }
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
+
+    return( 0 );
+#endif
+}
+
+static int ssl_parse_certificate_request( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   SSL version
+     *     6  .   6   cert type count
+     *     7  .. n-1  cert types
+     *     n  .. n+1  length of all DNs
+     *    n+2 .. n+3  length of DN 1
+     *    n+4 .. ...  Distinguished Name #1
+     *    ... .. ...  length of DN 2, etc.
+     */
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    ssl->client_auth = 0;
+    ssl->state++;
+
+    if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST )
+        ssl->client_auth++;
+
+    SSL_DEBUG_MSG( 3, ( "got %s certificate request",
+                        ssl->client_auth ? "a" : "no" ) );
+
+    SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
+
+    return( 0 );
+}
+
+static int ssl_parse_server_hello_done( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
+
+    if( ssl->client_auth != 0 )
+    {
+        if( ( ret = ssl_read_record( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+            return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+        }
+    }
+
+    if( ssl->in_hslen  != 4 ||
+        ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
+    }
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
+
+    return( 0 );
+}
+
+static int ssl_write_client_key_exchange( ssl_context *ssl )
+{
+    int ret;
+    size_t i, n;
+
+    SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
+
+    if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA)
+    {
+#if !defined(POLARSSL_DHM_C)
+        SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+        /*
+         * DHM key exchange -- send G^X mod P
+         */
+        n = ssl->dhm_ctx.len;
+
+        ssl->out_msg[4] = (unsigned char)( n >> 8 );
+        ssl->out_msg[5] = (unsigned char)( n      );
+        i = 6;
+
+        ret = dhm_make_public( &ssl->dhm_ctx, 256,
+                               &ssl->out_msg[i], n,
+                                ssl->f_rng, ssl->p_rng );
+        if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_make_public", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X  );
+        SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
+
+        ssl->pmslen = ssl->dhm_ctx.len;
+
+        if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
+                                      ssl->premaster,
+                                     &ssl->pmslen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K  );
+#endif
+    }
+    else
+    {
+        /*
+         * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster))
+         */
+        ssl->premaster[0] = (unsigned char) ssl->max_major_ver;
+        ssl->premaster[1] = (unsigned char) ssl->max_minor_ver;
+        ssl->pmslen = 48;
+
+        for( i = 2; i < ssl->pmslen; i++ )
+            ssl->premaster[i] = (unsigned char) ssl->f_rng( ssl->p_rng );
+
+        i = 4;
+        n = ssl->peer_cert->rsa.len;
+
+        if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+        {
+            i += 2;
+            ssl->out_msg[4] = (unsigned char)( n >> 8 );
+            ssl->out_msg[5] = (unsigned char)( n      );
+        }
+
+        ret = rsa_pkcs1_encrypt( &ssl->peer_cert->rsa,
+                                  ssl->f_rng, ssl->p_rng,
+                                  RSA_PUBLIC,
+                                  ssl->pmslen, ssl->premaster,
+                                  ssl->out_msg + i );
+        if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
+            return( ret );
+        }
+    }
+
+    if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+        return( ret );
+    }
+
+    ssl->out_msglen  = i + n;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CLIENT_KEY_EXCHANGE;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
+
+    return( 0 );
+}
+
+static int ssl_write_certificate_verify( ssl_context *ssl )
+{
+    int ret = 0;
+    size_t n = 0;
+    unsigned char hash[36];
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+
+    if( ssl->client_auth == 0 || ssl->own_cert == NULL )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ssl->rsa_key == NULL )
+    {
+#if defined(POLARSSL_PKCS11_C)
+        if( ssl->pkcs11_key == NULL )
+        {
+#endif /* defined(POLARSSL_PKCS11_C) */
+            SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+            return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+#if defined(POLARSSL_PKCS11_C)
+        }
+#endif /* defined(POLARSSL_PKCS11_C) */
+    }
+
+    /*
+     * Make an RSA signature of the handshake digests
+     */
+    ssl_calc_verify( ssl, hash );
+
+    if ( ssl->rsa_key )
+        n = ssl->rsa_key->len;
+#if defined(POLARSSL_PKCS11_C)
+    else
+        n = ssl->pkcs11_key->len;
+#endif  /* defined(POLARSSL_PKCS11_C) */
+
+    ssl->out_msg[4] = (unsigned char)( n >> 8 );
+    ssl->out_msg[5] = (unsigned char)( n      );
+
+    if( ssl->rsa_key )
+    {
+        ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
+                                    RSA_PRIVATE, SIG_RSA_RAW,
+                                    36, hash, ssl->out_msg + 6 );
+    } else {
+#if defined(POLARSSL_PKCS11_C)
+        ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, SIG_RSA_RAW,
+                                    36, hash, ssl->out_msg + 6 );
+#endif  /* defined(POLARSSL_PKCS11_C) */
+    }
+
+    if (ret != 0)
+    {
+        SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
+        return( ret );
+    }
+
+    ssl->out_msglen  = 6 + n;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CERTIFICATE_VERIFY;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
+
+    return( 0 );
+}
+
+/*
+ * SSL handshake -- client side
+ */
+int ssl_handshake_client( ssl_context *ssl )
+{
+    int ret = 0;
+
+    SSL_DEBUG_MSG( 2, ( "=> handshake client" ) );
+
+    while( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
+
+        if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+            break;
+
+        switch( ssl->state )
+        {
+            case SSL_HELLO_REQUEST:
+                ssl->state = SSL_CLIENT_HELLO;
+                break;
+
+            /*
+             *  ==>   ClientHello
+             */
+            case SSL_CLIENT_HELLO:
+                ret = ssl_write_client_hello( ssl );
+                break;
+
+            /*
+             *  <==   ServerHello
+             *        Certificate
+             *      ( ServerKeyExchange  )
+             *      ( CertificateRequest )
+             *        ServerHelloDone
+             */
+            case SSL_SERVER_HELLO:
+                ret = ssl_parse_server_hello( ssl );
+                break;
+
+            case SSL_SERVER_CERTIFICATE:
+                ret = ssl_parse_certificate( ssl );
+                break;
+
+            case SSL_SERVER_KEY_EXCHANGE:
+                ret = ssl_parse_server_key_exchange( ssl );
+                break;
+
+            case SSL_CERTIFICATE_REQUEST:
+                ret = ssl_parse_certificate_request( ssl );
+                break;
+
+            case SSL_SERVER_HELLO_DONE:
+                ret = ssl_parse_server_hello_done( ssl );
+                break;
+
+            /*
+             *  ==> ( Certificate/Alert  )
+             *        ClientKeyExchange
+             *      ( CertificateVerify  )
+             *        ChangeCipherSpec
+             *        Finished
+             */
+            case SSL_CLIENT_CERTIFICATE:
+                ret = ssl_write_certificate( ssl );
+                break;
+
+            case SSL_CLIENT_KEY_EXCHANGE:
+                ret = ssl_write_client_key_exchange( ssl );
+                break;
+
+            case SSL_CERTIFICATE_VERIFY:
+                ret = ssl_write_certificate_verify( ssl );
+                break;
+
+            case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+                ret = ssl_write_change_cipher_spec( ssl );
+                break;
+
+            case SSL_CLIENT_FINISHED:
+                ret = ssl_write_finished( ssl );
+                break;
+
+            /*
+             *  <==   ChangeCipherSpec
+             *        Finished
+             */
+            case SSL_SERVER_CHANGE_CIPHER_SPEC:
+                ret = ssl_parse_change_cipher_spec( ssl );
+                break;
+
+            case SSL_SERVER_FINISHED:
+                ret = ssl_parse_finished( ssl );
+                break;
+
+            case SSL_FLUSH_BUFFERS:
+                SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+                ssl->state = SSL_HANDSHAKE_OVER;
+                break;
+
+            default:
+                SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+                return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+        }
+
+        if( ret != 0 )
+            break;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= handshake client" ) );
+
+    return( ret );
+}
+
+#endif

+ 1029 - 0
thirdparty/PolarSSL/library/ssl_srv.c

@@ -0,0 +1,1029 @@
+/*
+ *  SSLv3/TLSv1 server-side functions
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#if defined(POLARSSL_SSL_SRV_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_PKCS11_C)
+#include "polarssl/pkcs11.h"
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+#include <stdlib.h>
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#include <time.h>
+#include "rtc.h"
+
+static int ssl_parse_client_hello( ssl_context *ssl )
+{
+    int ret;
+    unsigned int i, j;
+    size_t n;
+    unsigned int ciph_len, sess_len;
+    unsigned int chal_len, comp_len;
+    unsigned char *buf, *p;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
+
+    if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    buf = ssl->in_hdr;
+
+    if( ( buf[0] & 0x80 ) != 0 )
+    {
+        SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+        SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
+                       buf[2] ) );
+        SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
+                       ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
+        SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
+                       buf[3], buf[4] ) );
+
+        /*
+         * SSLv2 Client Hello
+         *
+         * Record layer:
+         *     0  .   1   message length
+         *
+         * SSL layer:
+         *     2  .   2   message type
+         *     3  .   4   protocol version
+         */
+        if( buf[2] != SSL_HS_CLIENT_HELLO ||
+            buf[3] != SSL_MAJOR_VERSION_3 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
+
+        if( n < 17 || n > 512 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        ssl->max_major_ver = buf[3];
+        ssl->max_minor_ver = buf[4];
+
+        ssl->major_ver = SSL_MAJOR_VERSION_3;
+        ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_2 )
+                         ? buf[4]  : SSL_MINOR_VERSION_2;
+
+        if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+            return( ret );
+        }
+
+         md5_update( &ssl->fin_md5 , buf + 2, n );
+        sha1_update( &ssl->fin_sha1, buf + 2, n );
+
+        buf = ssl->in_msg;
+        n = ssl->in_left - 5;
+
+        /*
+         *    0  .   1   ciphersuitelist length
+         *    2  .   3   session id length
+         *    4  .   5   challenge length
+         *    6  .  ..   ciphersuitelist
+         *   ..  .  ..   session id
+         *   ..  .  ..   challenge
+         */
+        SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+        ciph_len = ( buf[0] << 8 ) | buf[1];
+        sess_len = ( buf[2] << 8 ) | buf[3];
+        chal_len = ( buf[4] << 8 ) | buf[5];
+
+        SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
+                       ciph_len, sess_len, chal_len ) );
+
+        /*
+         * Make sure each parameter length is valid
+         */
+        if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        if( sess_len > 32 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        if( chal_len < 8 || chal_len > 32 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        if( n != 6 + ciph_len + sess_len + chal_len )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+                       buf + 6,  ciph_len );
+        SSL_DEBUG_BUF( 3, "client hello, session id",
+                       buf + 6 + ciph_len,  sess_len );
+        SSL_DEBUG_BUF( 3, "client hello, challenge",
+                       buf + 6 + ciph_len + sess_len,  chal_len );
+
+        p = buf + 6 + ciph_len;
+        ssl->session->length = sess_len;
+        memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
+        memcpy( ssl->session->id, p, ssl->session->length );
+
+        p += sess_len;
+        memset( ssl->randbytes, 0, 64 );
+        memcpy( ssl->randbytes + 32 - chal_len, p, chal_len );
+
+        for( i = 0; ssl->ciphersuites[i] != 0; i++ )
+        {
+            for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
+            {
+                if( p[0] == 0 &&
+                    p[1] == 0 &&
+                    p[2] == ssl->ciphersuites[i] )
+                    goto have_ciphersuite;
+            }
+        }
+    }
+    else
+    {
+        SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+        SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
+                       buf[0] ) );
+        SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
+                       ( buf[3] << 8 ) | buf[4] ) );
+        SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]",
+                       buf[1], buf[2] ) );
+
+        /*
+         * SSLv3 Client Hello
+         *
+         * Record layer:
+         *     0  .   0   message type
+         *     1  .   2   protocol version
+         *     3  .   4   message length
+         */
+        if( buf[0] != SSL_MSG_HANDSHAKE ||
+            buf[1] != SSL_MAJOR_VERSION_3 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        n = ( buf[3] << 8 ) | buf[4];
+
+        if( n < 45 || n > 512 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+            return( ret );
+        }
+
+        buf = ssl->in_msg;
+        n = ssl->in_left - 5;
+
+         md5_update( &ssl->fin_md5 , buf, n );
+        sha1_update( &ssl->fin_sha1, buf, n );
+
+        /*
+         * SSL layer:
+         *     0  .   0   handshake type
+         *     1  .   3   handshake length
+         *     4  .   5   protocol version
+         *     6  .   9   UNIX time()
+         *    10  .  37   random bytes
+         *    38  .  38   session id length
+         *    39  . 38+x  session id
+         *   39+x . 40+x  ciphersuitelist length
+         *   41+x .  ..   ciphersuitelist
+         *    ..  .  ..   compression alg.
+         *    ..  .  ..   extensions
+         */
+        SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+        SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d",
+                       buf[0] ) );
+        SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
+                       ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
+        SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]",
+                       buf[4], buf[5] ) );
+
+        /*
+         * Check the handshake type and protocol version
+         */
+        if( buf[0] != SSL_HS_CLIENT_HELLO ||
+            buf[4] != SSL_MAJOR_VERSION_3 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        ssl->major_ver = SSL_MAJOR_VERSION_3;
+        ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_2 )
+                         ? buf[5]  : SSL_MINOR_VERSION_2;
+
+        ssl->max_major_ver = buf[4];
+        ssl->max_minor_ver = buf[5];
+
+        memcpy( ssl->randbytes, buf + 6, 32 );
+
+        /*
+         * Check the handshake message length
+         */
+        if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        /*
+         * Check the session length
+         */
+        sess_len = buf[38];
+
+        if( sess_len > 32 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        ssl->session->length = sess_len;
+        memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
+        memcpy( ssl->session->id, buf + 39 , ssl->session->length );
+
+        /*
+         * Check the ciphersuitelist length
+         */
+        ciph_len = ( buf[39 + sess_len] << 8 )
+                 | ( buf[40 + sess_len]      );
+
+        if( ciph_len < 2 || ciph_len > 256 || ( ciph_len % 2 ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        /*
+         * Check the compression algorithms length
+         */
+        comp_len = buf[41 + sess_len + ciph_len];
+
+        if( comp_len < 1 || comp_len > 16 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+        }
+
+        SSL_DEBUG_BUF( 3, "client hello, random bytes",
+                       buf +  6,  32 );
+        SSL_DEBUG_BUF( 3, "client hello, session id",
+                       buf + 38,  sess_len );
+        SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+                       buf + 41 + sess_len,  ciph_len );
+        SSL_DEBUG_BUF( 3, "client hello, compression",
+                       buf + 42 + sess_len + ciph_len, comp_len );
+
+        /*
+         * Search for a matching ciphersuite
+         */
+        for( i = 0; ssl->ciphersuites[i] != 0; i++ )
+        {
+            for( j = 0, p = buf + 41 + sess_len; j < ciph_len;
+                j += 2, p += 2 )
+            {
+                if( p[0] == 0 && p[1] == ssl->ciphersuites[i] )
+                    goto have_ciphersuite;
+            }
+        }
+    }
+
+    SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+
+    return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+
+have_ciphersuite:
+
+    ssl->session->ciphersuite = ssl->ciphersuites[i];
+    ssl->in_left = 0;
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
+
+    return( 0 );
+}
+
+static int ssl_write_server_hello( ssl_context *ssl )
+{
+    time_t t;
+    int ret, i, n;
+    unsigned char *buf, *p;
+
+    SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   protocol version
+     *     6  .   9   UNIX time()
+     *    10  .  37   random bytes
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    *p++ = (unsigned char) ssl->major_ver;
+    *p++ = (unsigned char) ssl->minor_ver;
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+                   buf[4], buf[5] ) );
+
+    //t = time( NULL );
+    t = RTC_GetUnixTime();
+    //t = 100000;
+    
+    *p++ = (unsigned char)( t >> 24 );
+    *p++ = (unsigned char)( t >> 16 );
+    *p++ = (unsigned char)( t >>  8 );
+    *p++ = (unsigned char)( t       );
+
+    SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+
+    for( i = 28; i > 0; i-- )
+        *p++ = (unsigned char) ssl->f_rng( ssl->p_rng );
+
+    memcpy( ssl->randbytes + 32, buf + 6, 32 );
+
+    SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
+
+    /*
+     *    38  .  38   session id length
+     *    39  . 38+n  session id
+     *   39+n . 40+n  chosen ciphersuite
+     *   41+n . 41+n  chosen compression alg.
+     */
+    ssl->session->length = n = 32;
+    *p++ = (unsigned char) ssl->session->length;
+    
+    if( ssl->s_get == NULL ||
+        ssl->s_get( ssl ) != 0 )
+    {
+        /*
+         * Not found, create a new session id
+         */
+        ssl->resume = 0;
+        ssl->state++;
+
+        for( i = 0; i < n; i++ )
+            ssl->session->id[i] =
+                (unsigned char) ssl->f_rng( ssl->p_rng );
+    }
+    else
+    {
+        /*
+         * Found a matching session, resume it
+         */
+        ssl->resume = 1;
+        ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+        if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+            return( ret );
+        }
+    }
+    
+    memcpy( p, ssl->session->id, ssl->session->length );
+    p += ssl->session->length;
+
+    SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+    SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
+    SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+                   ssl->resume ? "a" : "no" ) );
+
+    *p++ = (unsigned char)( ssl->session->ciphersuite >> 8 );
+    *p++ = (unsigned char)( ssl->session->ciphersuite      );
+    *p++ = SSL_COMPRESS_NULL;
+
+    SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d",
+                   ssl->session->ciphersuite ) );
+    SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", 0 ) );
+
+    ssl->out_msglen  = p - buf;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_SERVER_HELLO;
+
+    ret = ssl_write_record( ssl );
+
+    SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
+
+    return( ret );
+}
+
+static int ssl_write_certificate_request( ssl_context *ssl )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf, *p;
+    const x509_cert *crt;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
+
+    ssl->state++;
+
+    if( ssl->authmode == SSL_VERIFY_NONE )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
+        return( 0 );
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   4   cert type count
+     *     5  .. n-1  cert types
+     *     n  .. n+1  length of all DNs
+     *    n+2 .. n+3  length of DN 1
+     *    n+4 .. ...  Distinguished Name #1
+     *    ... .. ...  length of DN 2, etc.
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    /*
+     * At the moment, only RSA certificates are supported
+     */
+    *p++ = 1;
+    *p++ = 1;
+
+    p += 2;
+    crt = ssl->ca_chain;
+
+    while( crt != NULL )
+    {
+        if( p - buf > 4096 )
+            break;
+
+        n = crt->subject_raw.len;
+        *p++ = (unsigned char)( n >> 8 );
+        *p++ = (unsigned char)( n      );
+        memcpy( p, crt->subject_raw.p, n );
+
+        SSL_DEBUG_BUF( 3, "requested DN", p, n );
+        p += n; crt = crt->next;
+    }
+
+    ssl->out_msglen  = n = p - buf;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CERTIFICATE_REQUEST;
+    ssl->out_msg[6]  = (unsigned char)( ( n - 8 ) >> 8 );
+    ssl->out_msg[7]  = (unsigned char)( ( n - 8 )      );
+
+    ret = ssl_write_record( ssl );
+
+    SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
+
+    return( ret );
+}
+
+static int ssl_write_server_key_exchange( ssl_context *ssl )
+{
+#if defined(POLARSSL_DHM_C)
+    int ret;
+    size_t n, rsa_key_len = 0;
+    unsigned char hash[36];
+    md5_context md5;
+    sha1_context sha1;
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
+
+    if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA &&
+        ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA)
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+#if !defined(POLARSSL_DHM_C)
+    SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
+    return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+
+    if( ssl->rsa_key == NULL )
+    {
+#if defined(POLARSSL_PKCS11_C)
+        if( ssl->pkcs11_key == NULL )
+        {
+#endif /* defined(POLARSSL_PKCS11_C) */
+            SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+            return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+#if defined(POLARSSL_PKCS11_C)
+        }
+#endif /* defined(POLARSSL_PKCS11_C) */
+    }
+
+    /*
+     * Ephemeral DH parameters:
+     *
+     * struct {
+     *     opaque dh_p<1..2^16-1>;
+     *     opaque dh_g<1..2^16-1>;
+     *     opaque dh_Ys<1..2^16-1>;
+     * } ServerDHParams;
+     */
+    if( ( ret = dhm_make_params( &ssl->dhm_ctx, 256, ssl->out_msg + 4,
+                                 &n, ssl->f_rng, ssl->p_rng ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "dhm_make_params", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X  );
+    SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P  );
+    SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G  );
+    SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
+
+    /*
+     * digitally-signed struct {
+     *     opaque md5_hash[16];
+     *     opaque sha_hash[20];
+     * };
+     *
+     * md5_hash
+     *     MD5(ClientHello.random + ServerHello.random
+     *                            + ServerParams);
+     * sha_hash
+     *     SHA(ClientHello.random + ServerHello.random
+     *                            + ServerParams);
+     */
+    md5_starts( &md5 );
+    md5_update( &md5, ssl->randbytes,  64 );
+    md5_update( &md5, ssl->out_msg + 4, n );
+    md5_finish( &md5, hash );
+
+    sha1_starts( &sha1 );
+    sha1_update( &sha1, ssl->randbytes,  64 );
+    sha1_update( &sha1, ssl->out_msg + 4, n );
+    sha1_finish( &sha1, hash + 16 );
+
+    SSL_DEBUG_BUF( 3, "parameters hash", hash, 36 );
+
+    if ( ssl->rsa_key )
+        rsa_key_len = ssl->rsa_key->len;
+#if defined(POLARSSL_PKCS11_C)
+    else
+        rsa_key_len = ssl->pkcs11_key->len;
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+    ssl->out_msg[4 + n] = (unsigned char)( rsa_key_len >> 8 );
+    ssl->out_msg[5 + n] = (unsigned char)( rsa_key_len      );
+
+    if ( ssl->rsa_key )
+    {
+        ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
+                              RSA_PRIVATE,
+                              SIG_RSA_RAW, 36, hash, ssl->out_msg + 6 + n );
+    }
+#if defined(POLARSSL_PKCS11_C)
+    else {
+        ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE,
+                              SIG_RSA_RAW, 36, hash, ssl->out_msg + 6 + n );
+    }
+#endif  /* defined(POLARSSL_PKCS11_C) */
+
+    if( ret != 0 )
+    {
+        SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_BUF( 3, "my RSA sig", ssl->out_msg + 6 + n, rsa_key_len );
+
+    ssl->out_msglen  = 6 + n + rsa_key_len;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_SERVER_KEY_EXCHANGE;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
+
+    return( 0 );
+#endif
+}
+
+static int ssl_write_server_hello_done( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
+
+    ssl->out_msglen  = 4;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_SERVER_HELLO_DONE;
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
+
+    return( 0 );
+}
+
+static int ssl_parse_client_key_exchange( ssl_context *ssl )
+{
+    int ret;
+    size_t i, n = 0;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+    }
+
+    if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+        ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA)
+    {
+#if !defined(POLARSSL_DHM_C)
+        SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+        /*
+         * Receive G^Y mod P, premaster = (G^Y)^X mod P
+         */
+        n = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+
+        if( n < 1 || n > ssl->dhm_ctx.len ||
+            n + 6 != ssl->in_hslen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
+        if( ( ret = dhm_read_public( &ssl->dhm_ctx,
+                                      ssl->in_msg + 6, n ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_read_public", ret );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP );
+        }
+
+        SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
+
+        ssl->pmslen = ssl->dhm_ctx.len;
+
+        if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
+                     ssl->premaster, &ssl->pmslen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS );
+        }
+
+        SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K  );
+#endif
+    }
+    else
+    {
+        if( ssl->rsa_key == NULL )
+        {
+#if defined(POLARSSL_PKCS11_C)
+                if( ssl->pkcs11_key == NULL )
+                {
+#endif
+                    SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+                    return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+#if defined(POLARSSL_PKCS11_C)
+                }
+#endif
+        }
+
+        /*
+         * Decrypt the premaster using own private RSA key
+         */
+        i = 4;
+        if( ssl->rsa_key )
+            n = ssl->rsa_key->len;
+#if defined(POLARSSL_PKCS11_C)
+        else
+            n = ssl->pkcs11_key->len;
+#endif
+        ssl->pmslen = 48;
+
+        if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+        {
+            i += 2;
+            if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) ||
+                ssl->in_msg[5] != ( ( n      ) & 0xFF ) )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+            }
+        }
+
+        if( ssl->in_hslen != i + n )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
+        if( ssl->rsa_key ) {
+            ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, &ssl->pmslen,
+                                 ssl->in_msg + i, ssl->premaster,
+                                 sizeof(ssl->premaster) );
+        }
+#if defined(POLARSSL_PKCS11_C)
+        else {
+            ret = pkcs11_decrypt( ssl->pkcs11_key, RSA_PRIVATE, &ssl->pmslen,
+                                 ssl->in_msg + i, ssl->premaster,
+                                 sizeof(ssl->premaster) );
+        }
+#endif  /* defined(POLARSSL_PKCS11_C) */
+
+        if( ret != 0 || ssl->pmslen != 48 ||
+            ssl->premaster[0] != ssl->max_major_ver ||
+            ssl->premaster[1] != ssl->max_minor_ver )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+
+            /*
+             * Protection against Bleichenbacher's attack:
+             * invalid PKCS#1 v1.5 padding must not cause
+             * the connection to end immediately; instead,
+             * send a bad_record_mac later in the handshake.
+             */
+            ssl->pmslen = 48;
+
+            for( i = 0; i < ssl->pmslen; i++ )
+                ssl->premaster[i] = (unsigned char) ssl->f_rng( ssl->p_rng );
+        }
+    }
+
+    if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+        return( ret );
+    }
+
+    if( ssl->s_set != NULL )
+        ssl->s_set( ssl );
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
+
+    return( 0 );
+}
+
+static int ssl_parse_certificate_verify( ssl_context *ssl )
+{
+    int ret;
+    size_t n1, n2;
+    unsigned char hash[36];
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
+
+    if( ssl->peer_cert == NULL )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    ssl_calc_verify( ssl, hash );
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    ssl->state++;
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+    }
+
+    if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+    }
+
+    n1 = ssl->peer_cert->rsa.len;
+    n2 = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+
+    if( n1 + 6 != ssl->in_hslen || n1 != n2 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+    }
+
+    ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
+                            SIG_RSA_RAW, 36, hash, ssl->in_msg + 6 );
+    if( ret != 0 )
+    {
+        SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
+
+    return( 0 );
+}
+
+/*
+ * SSL handshake -- server side
+ */
+int ssl_handshake_server( ssl_context *ssl )
+{
+    int ret = 0;
+
+    SSL_DEBUG_MSG( 2, ( "=> handshake server" ) );
+
+    while( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
+
+        if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+            break;
+
+        switch( ssl->state )
+        {
+            case SSL_HELLO_REQUEST:
+                ssl->state = SSL_CLIENT_HELLO;
+                break;
+
+            /*
+             *  <==   ClientHello
+             */
+            case SSL_CLIENT_HELLO:
+                ret = ssl_parse_client_hello( ssl );
+                break;
+
+            /*
+             *  ==>   ServerHello
+             *        Certificate
+             *      ( ServerKeyExchange  )
+             *      ( CertificateRequest )
+             *        ServerHelloDone
+             */
+            case SSL_SERVER_HELLO:
+                ret = ssl_write_server_hello( ssl );
+                break;
+
+            case SSL_SERVER_CERTIFICATE:
+                ret = ssl_write_certificate( ssl );
+                break;
+
+            case SSL_SERVER_KEY_EXCHANGE:
+                ret = ssl_write_server_key_exchange( ssl );
+                break;
+
+            case SSL_CERTIFICATE_REQUEST:
+                ret = ssl_write_certificate_request( ssl );
+                break;
+
+            case SSL_SERVER_HELLO_DONE:
+                ret = ssl_write_server_hello_done( ssl );
+                break;
+
+            /*
+             *  <== ( Certificate/Alert  )
+             *        ClientKeyExchange
+             *      ( CertificateVerify  )
+             *        ChangeCipherSpec
+             *        Finished
+             */
+            case SSL_CLIENT_CERTIFICATE:
+                ret = ssl_parse_certificate( ssl );
+                break;
+
+            case SSL_CLIENT_KEY_EXCHANGE:
+                ret = ssl_parse_client_key_exchange( ssl );
+                break;
+
+            case SSL_CERTIFICATE_VERIFY:
+                ret = ssl_parse_certificate_verify( ssl );
+                break;
+
+            case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+                ret = ssl_parse_change_cipher_spec( ssl );
+                break;
+
+            case SSL_CLIENT_FINISHED:
+                ret = ssl_parse_finished( ssl );
+                break;
+
+            /*
+             *  ==>   ChangeCipherSpec
+             *        Finished
+             */
+            case SSL_SERVER_CHANGE_CIPHER_SPEC:
+                ret = ssl_write_change_cipher_spec( ssl );
+                break;
+
+            case SSL_SERVER_FINISHED:
+                ret = ssl_write_finished( ssl );
+                break;
+
+            case SSL_FLUSH_BUFFERS:
+                SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+                ssl->state = SSL_HANDSHAKE_OVER;
+                break;
+
+            default:
+                SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+                return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+        }
+
+        if( ret != 0 )
+            break;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= handshake server" ) );
+
+    return( ret );
+}
+
+#endif

+ 2280 - 0
thirdparty/PolarSSL/library/ssl_tls.c

@@ -0,0 +1,2280 @@
+/*
+ *  SSLv3/TLSv1 shared functions
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program 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.
+ *
+ *  This program 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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  The SSL 3.0 specification was drafted by Netscape in 1996,
+ *  and became an IETF standard in 1999.
+ *
+ *  http://wp.netscape.com/eng/ssl3/
+ *  http://www.ietf.org/rfc/rfc2246.txt
+ *  http://www.ietf.org/rfc/rfc4346.txt
+ */
+
+#include "config.h"
+#include "FreeRTOS.h"
+#include "task.h"
+
+#if defined(POLARSSL_SSL_TLS_C)
+
+#include "polarssl/aes.h"
+#include "polarssl/arc4.h"
+#include "polarssl/camellia.h"
+#include "polarssl/des.h"
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#include <stdlib.h>
+#include <time.h>
+
+#include <stdlib.h>
+#if defined ( __GNUC__ )
+#include <my_strings.h>
+#endif
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+/*
+ * Key material generation
+ */
+static int tls1_prf( unsigned char *secret, size_t slen, char *label,
+                     unsigned char *random, size_t rlen,
+                     unsigned char *dstbuf, size_t dlen )
+{
+    size_t nb, hs;
+    size_t i, j, k;
+    unsigned char *S1, *S2;
+    unsigned char tmp[128];
+    unsigned char h_i[20];
+
+    if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    hs = ( slen + 1 ) / 2;
+    S1 = secret;
+    S2 = secret + slen - hs;
+
+    nb = strlen( label );
+    memcpy( tmp + 20, label, nb );
+    memcpy( tmp + 20 + nb, random, rlen );
+    nb += rlen;
+
+    /*
+     * First compute P_md5(secret,label+random)[0..dlen]
+     */
+    md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp );
+
+    for( i = 0; i < dlen; i += 16 )
+    {
+        md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i );
+        md5_hmac( S1, hs, 4 + tmp, 16,  4 + tmp );
+
+        k = ( i + 16 > dlen ) ? dlen % 16 : 16;
+
+        for( j = 0; j < k; j++ )
+            dstbuf[i + j]  = h_i[j];
+    }
+
+    /*
+     * XOR out with P_sha1(secret,label+random)[0..dlen]
+     */
+    sha1_hmac( S2, hs, tmp + 20, nb, tmp );
+
+    for( i = 0; i < dlen; i += 20 )
+    {
+        sha1_hmac( S2, hs, tmp, 20 + nb, h_i );
+        sha1_hmac( S2, hs, tmp, 20,      tmp );
+
+        k = ( i + 20 > dlen ) ? dlen % 20 : 20;
+
+        for( j = 0; j < k; j++ )
+            dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
+    }
+
+    memset( tmp, 0, sizeof( tmp ) );
+    memset( h_i, 0, sizeof( h_i ) );
+
+    return( 0 );
+}
+
+int ssl_derive_keys( ssl_context *ssl )
+{
+    int i;
+    md5_context md5;
+    sha1_context sha1;
+    unsigned char tmp[64];
+    unsigned char padding[16];
+    unsigned char sha1sum[20];
+    unsigned char keyblk[256];
+    unsigned char *key1;
+    unsigned char *key2;
+
+    SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
+
+    /*
+     * SSLv3:
+     *   master =
+     *     MD5( premaster + SHA1( 'A'   + premaster + randbytes ) ) +
+     *     MD5( premaster + SHA1( 'BB'  + premaster + randbytes ) ) +
+     *     MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
+     *
+     * TLSv1:
+     *   master = PRF( premaster, "master secret", randbytes )[0..47]
+     */
+    if( ssl->resume == 0 )
+    {
+        size_t len = ssl->pmslen;
+
+        SSL_DEBUG_BUF( 3, "premaster secret", ssl->premaster, len );
+
+        if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+        {
+            for( i = 0; i < 3; i++ )
+            {
+                memset( padding, 'A' + i, 1 + i );
+
+                sha1_starts( &sha1 );
+                sha1_update( &sha1, padding, 1 + i );
+                sha1_update( &sha1, ssl->premaster, len );
+                sha1_update( &sha1, ssl->randbytes,  64 );
+                sha1_finish( &sha1, sha1sum );
+
+                md5_starts( &md5 );
+                md5_update( &md5, ssl->premaster, len );
+                md5_update( &md5, sha1sum, 20 );
+                md5_finish( &md5, ssl->session->master + i * 16 );
+            }
+        }
+        else
+            tls1_prf( ssl->premaster, len, "master secret",
+                      ssl->randbytes, 64, ssl->session->master, 48 );
+
+        memset( ssl->premaster, 0, sizeof( ssl->premaster ) );
+    }
+    else
+        SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
+
+    /*
+     * Swap the client and server random values.
+     */
+    memcpy( tmp, ssl->randbytes, 64 );
+    memcpy( ssl->randbytes, tmp + 32, 32 );
+    memcpy( ssl->randbytes + 32, tmp, 32 );
+    memset( tmp, 0, sizeof( tmp ) );
+
+    /*
+     *  SSLv3:
+     *    key block =
+     *      MD5( master + SHA1( 'A'    + master + randbytes ) ) +
+     *      MD5( master + SHA1( 'BB'   + master + randbytes ) ) +
+     *      MD5( master + SHA1( 'CCC'  + master + randbytes ) ) +
+     *      MD5( master + SHA1( 'DDDD' + master + randbytes ) ) +
+     *      ...
+     *
+     *  TLSv1:
+     *    key block = PRF( master, "key expansion", randbytes )
+     */
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        for( i = 0; i < 16; i++ )
+        {
+            memset( padding, 'A' + i, 1 + i );
+
+            sha1_starts( &sha1 );
+            sha1_update( &sha1, padding, 1 + i );
+            sha1_update( &sha1, ssl->session->master, 48 );
+            sha1_update( &sha1, ssl->randbytes, 64 );
+            sha1_finish( &sha1, sha1sum );
+
+            md5_starts( &md5 );
+            md5_update( &md5, ssl->session->master, 48 );
+            md5_update( &md5, sha1sum, 20 );
+            md5_finish( &md5, keyblk + i * 16 );
+        }
+
+        memset( &md5,  0, sizeof( md5  ) );
+        memset( &sha1, 0, sizeof( sha1 ) );
+
+        memset( padding, 0, sizeof( padding ) );
+        memset( sha1sum, 0, sizeof( sha1sum ) );
+    }
+    else
+        tls1_prf( ssl->session->master, 48, "key expansion",
+                  ssl->randbytes, 64, keyblk, 256 );
+
+    SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) );
+    SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 );
+    SSL_DEBUG_BUF( 4, "random bytes", ssl->randbytes, 64 );
+    SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
+
+    memset( ssl->randbytes, 0, sizeof( ssl->randbytes ) );
+
+    /*
+     * Determine the appropriate key, IV and MAC length.
+     */
+    switch( ssl->session->ciphersuite )
+    {
+#if defined(POLARSSL_ARC4_C)
+        case SSL_RSA_RC4_128_MD5:
+            ssl->keylen = 16; ssl->minlen = 16;
+            ssl->ivlen  =  0; ssl->maclen = 16;
+            break;
+
+        case SSL_RSA_RC4_128_SHA:
+            ssl->keylen = 16; ssl->minlen = 20;
+            ssl->ivlen  =  0; ssl->maclen = 20;
+            break;
+#endif
+
+#if defined(POLARSSL_DES_C)
+        case SSL_RSA_DES_168_SHA:
+        case SSL_EDH_RSA_DES_168_SHA:
+            ssl->keylen = 24; ssl->minlen = 24;
+            ssl->ivlen  =  8; ssl->maclen = 20;
+            break;
+#endif
+
+#if defined(POLARSSL_AES_C)
+        case SSL_RSA_AES_128_SHA:
+        case SSL_EDH_RSA_AES_128_SHA:
+            ssl->keylen = 16; ssl->minlen = 32;
+            ssl->ivlen  = 16; ssl->maclen = 20;
+            break;
+
+        case SSL_RSA_AES_256_SHA:
+        case SSL_EDH_RSA_AES_256_SHA:
+            ssl->keylen = 32; ssl->minlen = 32;
+            ssl->ivlen  = 16; ssl->maclen = 20;
+            break;
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+        case SSL_RSA_CAMELLIA_128_SHA:
+        case SSL_EDH_RSA_CAMELLIA_128_SHA:
+            ssl->keylen = 16; ssl->minlen = 32;
+            ssl->ivlen  = 16; ssl->maclen = 20;
+            break;
+
+        case SSL_RSA_CAMELLIA_256_SHA:
+        case SSL_EDH_RSA_CAMELLIA_256_SHA:
+            ssl->keylen = 32; ssl->minlen = 32;
+            ssl->ivlen  = 16; ssl->maclen = 20;
+            break;
+#endif
+
+        default:
+            SSL_DEBUG_MSG( 1, ( "ciphersuite %s is not available",
+                           ssl_get_ciphersuite( ssl ) ) );
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d",
+                   ssl->keylen, ssl->minlen, ssl->ivlen, ssl->maclen ) );
+
+    /*
+     * Finally setup the cipher contexts, IVs and MAC secrets.
+     */
+    if( ssl->endpoint == SSL_IS_CLIENT )
+    {
+        key1 = keyblk + ssl->maclen * 2;
+        key2 = keyblk + ssl->maclen * 2 + ssl->keylen;
+
+        memcpy( ssl->mac_enc, keyblk,  ssl->maclen );
+        memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen );
+
+        /*
+         * This is not used in TLS v1.1.
+         */
+        memcpy( ssl->iv_enc, key2 + ssl->keylen,  ssl->ivlen );
+        memcpy( ssl->iv_dec, key2 + ssl->keylen + ssl->ivlen,
+                ssl->ivlen );
+    }
+    else
+    {
+        key1 = keyblk + ssl->maclen * 2 + ssl->keylen;
+        key2 = keyblk + ssl->maclen * 2;
+
+        memcpy( ssl->mac_dec, keyblk,  ssl->maclen );
+        memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen );
+
+        /*
+         * This is not used in TLS v1.1.
+         */
+        memcpy( ssl->iv_dec, key1 + ssl->keylen,  ssl->ivlen );
+        memcpy( ssl->iv_enc, key1 + ssl->keylen + ssl->ivlen,
+                ssl->ivlen );
+    }
+
+    switch( ssl->session->ciphersuite )
+    {
+#if defined(POLARSSL_ARC4_C)
+        case SSL_RSA_RC4_128_MD5:
+        case SSL_RSA_RC4_128_SHA:
+            arc4_setup( (arc4_context *) ssl->ctx_enc, key1, ssl->keylen );
+            arc4_setup( (arc4_context *) ssl->ctx_dec, key2, ssl->keylen );
+            break;
+#endif
+
+#if defined(POLARSSL_DES_C)
+        case SSL_RSA_DES_168_SHA:
+        case SSL_EDH_RSA_DES_168_SHA:
+            des3_set3key_enc( (des3_context *) ssl->ctx_enc, key1 );
+            des3_set3key_dec( (des3_context *) ssl->ctx_dec, key2 );
+            break;
+#endif
+
+#if defined(POLARSSL_AES_C)
+        case SSL_RSA_AES_128_SHA:
+        case SSL_EDH_RSA_AES_128_SHA:
+            aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 128 );
+            aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 128 );
+            break;
+
+        case SSL_RSA_AES_256_SHA:
+        case SSL_EDH_RSA_AES_256_SHA:
+            aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 256 );
+            aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 256 );
+            break;
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+        case SSL_RSA_CAMELLIA_128_SHA:
+        case SSL_EDH_RSA_CAMELLIA_128_SHA:
+            camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 128 );
+            camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 128 );
+            break;
+
+        case SSL_RSA_CAMELLIA_256_SHA:
+        case SSL_EDH_RSA_CAMELLIA_256_SHA:
+            camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 256 );
+            camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 256 );
+            break;
+#endif
+
+        default:
+            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    memset( keyblk, 0, sizeof( keyblk ) );
+
+    SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
+
+    return( 0 );
+}
+
+void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] )
+{
+    md5_context md5;
+    sha1_context sha1;
+    unsigned char pad_1[48];
+    unsigned char pad_2[48];
+
+    SSL_DEBUG_MSG( 2, ( "=> calc verify" ) );
+
+    memcpy( &md5 , &ssl->fin_md5 , sizeof(  md5_context ) );
+    memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) );
+
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        memset( pad_1, 0x36, 48 );
+        memset( pad_2, 0x5C, 48 );
+
+        md5_update( &md5, ssl->session->master, 48 );
+        md5_update( &md5, pad_1, 48 );
+        md5_finish( &md5, hash );
+
+        md5_starts( &md5 );
+        md5_update( &md5, ssl->session->master, 48 );
+        md5_update( &md5, pad_2, 48 );
+        md5_update( &md5, hash,  16 );
+        md5_finish( &md5, hash );
+        
+        sha1_update( &sha1, ssl->session->master, 48 );
+        sha1_update( &sha1, pad_1, 40 );
+        sha1_finish( &sha1, hash + 16 );
+
+        sha1_starts( &sha1 );
+        sha1_update( &sha1, ssl->session->master, 48 );
+        sha1_update( &sha1, pad_2, 40 );
+        sha1_update( &sha1, hash + 16, 20 );
+        sha1_finish( &sha1, hash + 16 );
+    }
+    else /* TLSv1 */
+    {
+         md5_finish( &md5,  hash );
+        sha1_finish( &sha1, hash + 16 );
+    }
+
+    SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+    SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+    return;
+}
+
+/*
+ * SSLv3.0 MAC functions
+ */
+static void ssl_mac_md5( unsigned char *secret,
+                         unsigned char *buf, size_t len,
+                         unsigned char *ctr, int type )
+{
+    unsigned char header[11];
+    unsigned char padding[48];
+    md5_context md5;
+
+    memcpy( header, ctr, 8 );
+    header[ 8] = (unsigned char)  type;
+    header[ 9] = (unsigned char)( len >> 8 );
+    header[10] = (unsigned char)( len      );
+
+    memset( padding, 0x36, 48 );
+    md5_starts( &md5 );
+    md5_update( &md5, secret,  16 );
+    md5_update( &md5, padding, 48 );
+    md5_update( &md5, header,  11 );
+    md5_update( &md5, buf,  len );
+    md5_finish( &md5, buf + len );
+
+    memset( padding, 0x5C, 48 );
+    md5_starts( &md5 );
+    md5_update( &md5, secret,  16 );
+    md5_update( &md5, padding, 48 );
+    md5_update( &md5, buf + len, 16 );
+    md5_finish( &md5, buf + len );
+}
+
+static void ssl_mac_sha1( unsigned char *secret,
+                          unsigned char *buf, size_t len,
+                          unsigned char *ctr, int type )
+{
+    unsigned char header[11];
+    unsigned char padding[40];
+    sha1_context sha1;
+
+    memcpy( header, ctr, 8 );
+    header[ 8] = (unsigned char)  type;
+    header[ 9] = (unsigned char)( len >> 8 );
+    header[10] = (unsigned char)( len      );
+
+    memset( padding, 0x36, 40 );
+    sha1_starts( &sha1 );
+    sha1_update( &sha1, secret,  20 );
+    sha1_update( &sha1, padding, 40 );
+    sha1_update( &sha1, header,  11 );
+    sha1_update( &sha1, buf,  len );
+    sha1_finish( &sha1, buf + len );
+
+    memset( padding, 0x5C, 40 );
+    sha1_starts( &sha1 );
+    sha1_update( &sha1, secret,  20 );
+    sha1_update( &sha1, padding, 40 );
+    sha1_update( &sha1, buf + len, 20 );
+    sha1_finish( &sha1, buf + len );
+}
+
+/*
+ * Encryption/decryption functions
+ */ 
+static int ssl_encrypt_buf( ssl_context *ssl )
+{
+    size_t i, padlen;
+
+    SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
+
+    /*
+     * Add MAC then encrypt
+     */
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        if( ssl->maclen == 16 )
+             ssl_mac_md5( ssl->mac_enc,
+                          ssl->out_msg, ssl->out_msglen,
+                          ssl->out_ctr, ssl->out_msgtype );
+
+        if( ssl->maclen == 20 )
+            ssl_mac_sha1( ssl->mac_enc,
+                          ssl->out_msg, ssl->out_msglen,
+                          ssl->out_ctr, ssl->out_msgtype );
+    }
+    else
+    {
+        if( ssl->maclen == 16 )
+             md5_hmac( ssl->mac_enc, 16,
+                       ssl->out_ctr,  ssl->out_msglen + 13,
+                       ssl->out_msg + ssl->out_msglen );
+
+        if( ssl->maclen == 20 )
+            sha1_hmac( ssl->mac_enc, 20,
+                       ssl->out_ctr,  ssl->out_msglen + 13,
+                       ssl->out_msg + ssl->out_msglen );               
+    }
+
+    SSL_DEBUG_BUF( 4, "computed mac",
+                   ssl->out_msg + ssl->out_msglen, ssl->maclen );
+
+    ssl->out_msglen += ssl->maclen;
+
+    for( i = 8; i > 0; i-- )
+        if( ++ssl->out_ctr[i - 1] != 0 )
+            break;
+
+    if( ssl->ivlen == 0 )
+    {
+#if defined(POLARSSL_ARC4_C)
+        padlen = 0;
+
+        SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+                            "including %d bytes of padding",
+                       ssl->out_msglen, 0 ) );
+
+        SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+                       ssl->out_msg, ssl->out_msglen );
+
+        arc4_crypt( (arc4_context *) ssl->ctx_enc,
+                    ssl->out_msglen, ssl->out_msg,
+                    ssl->out_msg );
+#else
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif
+    }
+    else
+    {
+        unsigned char *enc_msg;
+        size_t enc_msglen;
+
+        padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen;
+        if( padlen == ssl->ivlen )
+            padlen = 0;
+
+        for( i = 0; i <= padlen; i++ )
+            ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen;
+
+        ssl->out_msglen += padlen + 1;
+
+        enc_msglen = ssl->out_msglen;
+        enc_msg = ssl->out_msg;
+
+        /*
+         * Prepend per-record IV for block cipher in TLS v1.1 as per
+         * Method 1 (6.2.3.2. in RFC4346)
+         */
+        if( ssl->minor_ver == SSL_MINOR_VERSION_2 )
+        {
+            /*
+             * Generate IV
+             */
+            for( i = 0; i < ssl->ivlen; i++ )
+                ssl->iv_enc[i] = ssl->f_rng( ssl->p_rng );
+
+            /*
+             * Shift message for ivlen bytes and prepend IV
+             */
+            memmove( ssl->out_msg + ssl->ivlen, ssl->out_msg, ssl->out_msglen );
+            memcpy( ssl->out_msg, ssl->iv_enc, ssl->ivlen );
+
+            /*
+             * Fix pointer positions and message length with added IV
+             */
+            enc_msg = ssl->out_msg + ssl->ivlen;
+            enc_msglen = ssl->out_msglen;
+            ssl->out_msglen += ssl->ivlen;
+        }
+
+        SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+                            "including %d bytes of IV and %d bytes of padding",
+                       ssl->out_msglen, ssl->ivlen, padlen + 1 ) );
+
+        SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+                       ssl->out_msg, ssl->out_msglen );
+
+        switch( ssl->ivlen )
+        {
+            case  8:
+#if defined(POLARSSL_DES_C)
+                des3_crypt_cbc( (des3_context *) ssl->ctx_enc,
+                    DES_ENCRYPT, enc_msglen,
+                    ssl->iv_enc, enc_msg, enc_msg );
+                break;
+#endif
+
+            case 16:
+#if defined(POLARSSL_AES_C)
+        if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+             ssl->session->ciphersuite == SSL_RSA_AES_256_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA)
+        {
+                    aes_crypt_cbc( (aes_context *) ssl->ctx_enc,
+                        AES_ENCRYPT, enc_msglen,
+                        ssl->iv_enc, enc_msg, enc_msg);
+                    break;
+        }
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+        if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+             ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA)
+        {
+                    camellia_crypt_cbc( (camellia_context *) ssl->ctx_enc,
+                        CAMELLIA_ENCRYPT, enc_msglen,
+                        ssl->iv_enc, enc_msg, enc_msg );
+                    break;
+        }
+#endif
+
+            default:
+                return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
+
+    return( 0 );
+}
+
+static int ssl_decrypt_buf( ssl_context *ssl )
+{
+    size_t i, padlen;
+    unsigned char tmp[20];
+
+    SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
+
+    if( ssl->in_msglen < ssl->minlen )
+    {
+        SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)",
+                       ssl->in_msglen, ssl->minlen ) );
+        return( POLARSSL_ERR_SSL_INVALID_MAC );
+    }
+
+    if( ssl->ivlen == 0 )
+    {
+#if defined(POLARSSL_ARC4_C)
+        padlen = 0;
+        arc4_crypt( (arc4_context *) ssl->ctx_dec,
+                    ssl->in_msglen, ssl->in_msg,
+                    ssl->in_msg );
+#else
+        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif
+    }
+    else
+    {
+        unsigned char *dec_msg;
+        unsigned char *dec_msg_result;
+        size_t dec_msglen;
+
+        /*
+         * Decrypt and check the padding
+         */
+        if( ssl->in_msglen % ssl->ivlen != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
+                           ssl->in_msglen, ssl->ivlen ) );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+
+        dec_msglen = ssl->in_msglen;
+        dec_msg = ssl->in_msg;
+        dec_msg_result = ssl->in_msg;
+
+        /*
+         * Initialize for prepended IV for block cipher in TLS v1.1
+         */
+        if( ssl->minor_ver == SSL_MINOR_VERSION_2 )
+        {
+            dec_msg += ssl->ivlen;
+            dec_msglen -= ssl->ivlen;
+            ssl->in_msglen -= ssl->ivlen;
+
+            for( i = 0; i < ssl->ivlen; i++ )
+                ssl->iv_dec[i] = ssl->in_msg[i];
+        }
+
+        switch( ssl->ivlen )
+        {
+#if defined(POLARSSL_DES_C)
+            case  8:
+                des3_crypt_cbc( (des3_context *) ssl->ctx_dec,
+                    DES_DECRYPT, dec_msglen,
+                    ssl->iv_dec, dec_msg, dec_msg_result );
+                break;
+#endif
+
+            case 16:
+#if defined(POLARSSL_AES_C)
+        if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+             ssl->session->ciphersuite == SSL_RSA_AES_256_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA)
+        {
+                    aes_crypt_cbc( (aes_context *) ssl->ctx_dec,
+                       AES_DECRYPT, dec_msglen,
+                       ssl->iv_dec, dec_msg, dec_msg_result );
+                    break;
+        }
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+        if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+             ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA ||
+             ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA)
+        {
+                    camellia_crypt_cbc( (camellia_context *) ssl->ctx_dec,
+                       CAMELLIA_DECRYPT, dec_msglen,
+                       ssl->iv_dec, dec_msg, dec_msg_result );
+                    break;
+        }
+#endif
+
+            default:
+                return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        }
+
+        padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
+
+        if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+        {
+            if( padlen > ssl->ivlen )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
+                                    "should be no more than %d",
+                               padlen, ssl->ivlen ) );
+                padlen = 0;
+            }
+        }
+        else
+        {
+            /*
+             * TLSv1: always check the padding
+             */
+            for( i = 1; i <= padlen; i++ )
+            {
+                if( ssl->in_msg[ssl->in_msglen - i] != padlen - 1 )
+                {
+                    SSL_DEBUG_MSG( 1, ( "bad padding byte: should be "
+                                        "%02x, but is %02x", padlen - 1,
+                                   ssl->in_msg[ssl->in_msglen - i] ) );
+                    padlen = 0;
+                }
+            }
+        }
+    }
+
+    SSL_DEBUG_BUF( 4, "raw buffer after decryption",
+                   ssl->in_msg, ssl->in_msglen );
+
+    /*
+     * Always compute the MAC (RFC4346, CBCTIME).
+     */
+    ssl->in_msglen -= ( ssl->maclen + padlen );
+
+    ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
+    ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen      );
+
+    memcpy( tmp, ssl->in_msg + ssl->in_msglen, 20 );
+
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        if( ssl->maclen == 16 )
+             ssl_mac_md5( ssl->mac_dec,
+                          ssl->in_msg, ssl->in_msglen,
+                          ssl->in_ctr, ssl->in_msgtype );
+        else
+            ssl_mac_sha1( ssl->mac_dec,
+                          ssl->in_msg, ssl->in_msglen,
+                          ssl->in_ctr, ssl->in_msgtype );
+    }
+    else
+    {
+        if( ssl->maclen == 16 )
+             md5_hmac( ssl->mac_dec, 16,
+                       ssl->in_ctr,  ssl->in_msglen + 13,
+                       ssl->in_msg + ssl->in_msglen );
+        else
+            sha1_hmac( ssl->mac_dec, 20,
+                       ssl->in_ctr,  ssl->in_msglen + 13,
+                       ssl->in_msg + ssl->in_msglen );
+    }
+
+    SSL_DEBUG_BUF( 4, "message  mac", tmp, ssl->maclen );
+    SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
+                   ssl->maclen );
+
+    if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
+                     ssl->maclen ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+        return( POLARSSL_ERR_SSL_INVALID_MAC );
+    }
+
+    /*
+     * Finally check the padding length; bad padding
+     * will produce the same error as an invalid MAC.
+     */
+    if( ssl->ivlen != 0 && padlen == 0 )
+        return( POLARSSL_ERR_SSL_INVALID_MAC );
+
+    if( ssl->in_msglen == 0 )
+    {
+        ssl->nb_zero++;
+
+        /*
+         * Three or more empty messages may be a DoS attack
+         * (excessive CPU consumption).
+         */
+        if( ssl->nb_zero > 3 )
+        {
+            SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
+                                "messages, possible DoS attack" ) );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+    }
+    else
+        ssl->nb_zero = 0;
+            
+    for( i = 8; i > 0; i-- )
+        if( ++ssl->in_ctr[i - 1] != 0 )
+            break;
+
+    SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
+
+    return( 0 );
+}
+
+/*
+ * Fill the input message buffer
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
+{
+    int ret;
+    size_t len;
+
+    SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
+
+    while( ssl->in_left < nb_want )
+    {
+        len = nb_want - ssl->in_left;
+        ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len );
+
+        SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+                       ssl->in_left, nb_want ) );
+        SSL_DEBUG_RET( 2, "ssl->f_recv", ret );
+
+        if( ret == 0 )
+            return( POLARSSL_ERR_SSL_CONN_EOF );
+
+        if( ret < 0 )
+            return( ret );
+
+        ssl->in_left += ret;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
+
+    return( 0 );
+}
+
+/*
+ * Flush any data not yet written
+ */
+int ssl_flush_output( ssl_context *ssl )
+{
+    int ret;
+    unsigned char *buf;
+
+    SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
+
+    while( ssl->out_left > 0 )
+    {
+        SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
+                       5 + ssl->out_msglen, ssl->out_left ) );
+
+        buf = ssl->out_hdr + 5 + ssl->out_msglen - ssl->out_left;
+        ret = ssl->f_send( ssl->p_send, buf, ssl->out_left );
+        SSL_DEBUG_RET( 2, "ssl->f_send", ret );
+
+        if( ret <= 0 )
+            return( ret );
+
+        ssl->out_left -= ret;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
+
+    return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+int ssl_write_record( ssl_context *ssl )
+{
+    int ret;
+    size_t len = ssl->out_msglen;
+
+    SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+
+    ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
+    ssl->out_hdr[1] = (unsigned char) ssl->major_ver;
+    ssl->out_hdr[2] = (unsigned char) ssl->minor_ver;
+    ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+    ssl->out_hdr[4] = (unsigned char)( len      );
+
+    if( ssl->out_msgtype == SSL_MSG_HANDSHAKE )
+    {
+        ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
+        ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >>  8 );
+        ssl->out_msg[3] = (unsigned char)( ( len - 4 )       );
+
+         md5_update( &ssl->fin_md5 , ssl->out_msg, len );
+        sha1_update( &ssl->fin_sha1, ssl->out_msg, len );
+    }
+
+    if( ssl->do_crypt != 0 )
+    {
+        if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
+            return( ret );
+        }
+
+        len = ssl->out_msglen;
+        ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+        ssl->out_hdr[4] = (unsigned char)( len      );
+    }
+
+    ssl->out_left = 5 + ssl->out_msglen;
+
+    SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
+                        "version = [%d:%d], msglen = %d",
+                   ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
+                 ( ssl->out_hdr[3] << 8 ) | ssl->out_hdr[4] ) );
+
+    SSL_DEBUG_BUF( 4, "output record sent to network",
+                   ssl->out_hdr, 5 + ssl->out_msglen );
+
+    if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write record" ) );
+
+    return( 0 );
+}
+
+int ssl_read_record( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> read record" ) );
+
+    if( ssl->in_hslen != 0 &&
+        ssl->in_hslen < ssl->in_msglen )
+    {
+        /*
+         * Get next Handshake message in the current record
+         */
+        ssl->in_msglen -= ssl->in_hslen;
+
+        memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
+                ssl->in_msglen );
+
+        ssl->in_hslen  = 4;
+        ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+        SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+                            " %d, type = %d, hslen = %d",
+                       ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+        if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->in_msglen < ssl->in_hslen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+         md5_update( &ssl->fin_md5 , ssl->in_msg, ssl->in_hslen );
+        sha1_update( &ssl->fin_sha1, ssl->in_msg, ssl->in_hslen );
+
+        return( 0 );
+    }
+
+    ssl->in_hslen = 0;
+
+    /*
+     * Read the record header and validate it
+     */
+    if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    ssl->in_msgtype =  ssl->in_hdr[0];
+    ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4];
+
+    SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
+                        "version = [%d:%d], msglen = %d",
+                     ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2],
+                   ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) );
+
+    if( ssl->in_hdr[1] != ssl->major_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+        return( POLARSSL_ERR_SSL_INVALID_RECORD );
+    }
+
+    if( ssl->in_hdr[2] > ssl->max_minor_ver )
+    {
+        SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+        return( POLARSSL_ERR_SSL_INVALID_RECORD );
+    }
+
+    /*
+     * Make sure the message length is acceptable
+     */
+    if( ssl->do_crypt == 0 )
+    {
+        if( ssl->in_msglen < 1 ||
+            ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+    }
+    else
+    {
+        if( ssl->in_msglen < ssl->minlen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->minor_ver == SSL_MINOR_VERSION_0 &&
+            ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        /*
+         * TLS encrypted messages can have up to 256 bytes of padding
+         */
+        if( ssl->minor_ver == SSL_MINOR_VERSION_1 &&
+            ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+    }
+
+    /*
+     * Read and optionally decrypt the message contents
+     */
+    if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_BUF( 4, "input record from network",
+                   ssl->in_hdr, 5 + ssl->in_msglen );
+
+    if( ssl->do_crypt != 0 )
+    {
+        if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_BUF( 4, "input payload after decrypt",
+                       ssl->in_msg, ssl->in_msglen );
+
+        if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+    }
+
+    if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
+    {
+        ssl->in_hslen  = 4;
+        ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+        SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+                            " %d, type = %d, hslen = %d",
+                       ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+        /*
+         * Additional checks to validate the handshake header
+         */
+        if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+        if( ssl->in_msglen < ssl->in_hslen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+            return( POLARSSL_ERR_SSL_INVALID_RECORD );
+        }
+
+         md5_update( &ssl->fin_md5 , ssl->in_msg, ssl->in_hslen );
+        sha1_update( &ssl->fin_sha1, ssl->in_msg, ssl->in_hslen );
+    }
+
+    if( ssl->in_msgtype == SSL_MSG_ALERT )
+    {
+        SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
+                       ssl->in_msg[0], ssl->in_msg[1] ) );
+
+        /*
+         * Ignore non-fatal alerts, except close_notify
+         */
+        if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL )
+        {
+            SSL_DEBUG_MSG( 1, ( "is a fatal alert message" ) );
+            /**
+             * Subtract from error code as ssl->in_msg[1] is 7-bit positive
+             * error identifier.
+             */
+            return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE - ssl->in_msg[1] );
+        }
+
+        if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+            ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY )
+        {
+            SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
+            return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY );
+        }
+    }
+
+    ssl->in_left = 0;
+
+    SSL_DEBUG_MSG( 2, ( "<= read record" ) );
+
+    return( 0 );
+}
+
+/*
+ * Handshake functions
+ */
+int ssl_write_certificate( ssl_context *ssl )
+{
+    int ret;
+    size_t i, n;
+    const x509_cert *crt;
+
+    SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
+
+    if( ssl->endpoint == SSL_IS_CLIENT )
+    {
+        if( ssl->client_auth == 0 )
+        {
+            SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+            ssl->state++;
+            return( 0 );
+        }
+
+        /*
+         * If using SSLv3 and got no cert, send an Alert message
+         * (otherwise an empty Certificate message will be sent).
+         */
+        if( ssl->own_cert  == NULL &&
+            ssl->minor_ver == SSL_MINOR_VERSION_0 )
+        {
+            ssl->out_msglen  = 2;
+            ssl->out_msgtype = SSL_MSG_ALERT;
+            ssl->out_msg[0]  = SSL_ALERT_LEVEL_WARNING;
+            ssl->out_msg[1]  = SSL_ALERT_MSG_NO_CERT;
+
+            SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
+            goto write_msg;
+        }
+    }
+    else /* SSL_IS_SERVER */
+    {
+        if( ssl->own_cert == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
+            return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED );
+        }
+    }
+
+    SSL_DEBUG_CRT( 3, "own certificate", ssl->own_cert );
+
+    /*
+     *     0  .  0    handshake type
+     *     1  .  3    handshake length
+     *     4  .  6    length of all certs
+     *     7  .  9    length of cert. 1
+     *    10  . n-1   peer certificate
+     *     n  . n+2   length of cert. 2
+     *    n+3 . ...   upper level cert, etc.
+     */
+    i = 7;
+    crt = ssl->own_cert;
+
+    while( crt != NULL )
+    {
+        n = crt->raw.len;
+        if( i + 3 + n > SSL_MAX_CONTENT_LEN )
+        {
+            SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
+                           i + 3 + n, SSL_MAX_CONTENT_LEN ) );
+            return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
+        }
+
+        ssl->out_msg[i    ] = (unsigned char)( n >> 16 );
+        ssl->out_msg[i + 1] = (unsigned char)( n >>  8 );
+        ssl->out_msg[i + 2] = (unsigned char)( n       );
+
+        i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
+        i += n; crt = crt->next;
+    }
+
+    ssl->out_msg[4]  = (unsigned char)( ( i - 7 ) >> 16 );
+    ssl->out_msg[5]  = (unsigned char)( ( i - 7 ) >>  8 );
+    ssl->out_msg[6]  = (unsigned char)( ( i - 7 )       );
+
+    ssl->out_msglen  = i;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_CERTIFICATE;
+
+write_msg:
+
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write certificate" ) );
+
+    return( 0 );
+}
+
+int ssl_parse_certificate( ssl_context *ssl )
+{
+    int ret;
+    size_t i, n;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+    if( ssl->endpoint == SSL_IS_SERVER &&
+        ssl->authmode == SSL_VERIFY_NONE )
+    {
+        ssl->verify_result = BADCERT_SKIP_VERIFY;
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    ssl->state++;
+
+    /*
+     * Check if the client sent an empty certificate
+     */
+    if( ssl->endpoint  == SSL_IS_SERVER &&
+        ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        if( ssl->in_msglen  == 2                        &&
+            ssl->in_msgtype == SSL_MSG_ALERT            &&
+            ssl->in_msg[0]  == SSL_ALERT_LEVEL_WARNING  &&
+            ssl->in_msg[1]  == SSL_ALERT_MSG_NO_CERT )
+        {
+            SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
+
+            ssl->verify_result = BADCERT_MISSING;
+            if( ssl->authmode == SSL_VERIFY_OPTIONAL )
+                return( 0 );
+            else
+                return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+        }
+    }
+
+    if( ssl->endpoint  == SSL_IS_SERVER &&
+        ssl->minor_ver != SSL_MINOR_VERSION_0 )
+    {
+        if( ssl->in_hslen   == 7                    &&
+            ssl->in_msgtype == SSL_MSG_HANDSHAKE    &&
+            ssl->in_msg[0]  == SSL_HS_CERTIFICATE   &&
+            memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
+
+            ssl->verify_result = BADCERT_MISSING;
+            if( ssl->authmode == SSL_VERIFY_REQUIRED )
+                return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+            else
+                return( 0 );
+        }
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+    }
+
+    /*
+     * Same message structure as in ssl_write_certificate()
+     */
+    n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6];
+
+    if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+    }
+
+    if( ( ssl->peer_cert = (x509_cert *) malloc(
+                    sizeof( x509_cert ) ) ) == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed",
+                       sizeof( x509_cert ) ) );
+        return( 1 );
+    }
+
+    memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
+
+    i = 7;
+
+    while( i < ssl->in_hslen )
+    {
+        if( ssl->in_msg[i] != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+
+        n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
+            | (unsigned int) ssl->in_msg[i + 2];
+        i += 3;
+
+        if( n < 128 || i + n > ssl->in_hslen )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+
+        ret = x509parse_crt( ssl->peer_cert, ssl->in_msg + i, n );
+        if( ret != 0 )
+        {
+            SSL_DEBUG_RET( 1, " x509parse_crt", ret );
+            return( ret );
+        }
+
+        i += n;
+    }
+
+    SSL_DEBUG_CRT( 3, "peer certificate", ssl->peer_cert );
+
+    if( ssl->authmode != SSL_VERIFY_NONE )
+    {
+        if( ssl->ca_chain == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
+            return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
+        }
+
+        ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain, ssl->ca_crl,
+                                ssl->peer_cn,  &ssl->verify_result,
+                                ssl->f_vrfy, ssl->p_vrfy );
+
+        if( ret != 0 )
+            SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+
+        if( ssl->authmode != SSL_VERIFY_REQUIRED )
+            ret = 0;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
+
+    return( ret );
+}
+
+int ssl_write_change_cipher_spec( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
+
+    ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC;
+    ssl->out_msglen  = 1;
+    ssl->out_msg[0]  = 1;
+
+    ssl->do_crypt = 0;
+    ssl->state++;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
+
+    return( 0 );
+}
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
+
+    ssl->do_crypt = 0;
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
+    }
+
+    ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
+
+    return( 0 );
+}
+
+static void ssl_calc_finished(
+                ssl_context *ssl, unsigned char *buf, int from,
+                md5_context *md5, sha1_context *sha1 )
+{
+    int len = 12;
+    char *sender;
+    unsigned char padbuf[48];
+    unsigned char md5sum[16];
+    unsigned char sha1sum[20];
+
+    SSL_DEBUG_MSG( 2, ( "=> calc  finished" ) );
+
+    /*
+     * SSLv3:
+     *   hash =
+     *      MD5( master + pad2 +
+     *          MD5( handshake + sender + master + pad1 ) )
+     *   + SHA1( master + pad2 +
+     *         SHA1( handshake + sender + master + pad1 ) )
+     *
+     * TLSv1:
+     *   hash = PRF( master, finished_label,
+     *               MD5( handshake ) + SHA1( handshake ) )[0..11]
+     */
+
+    SSL_DEBUG_BUF( 4, "finished  md5 state", (unsigned char *)
+                    md5->state, sizeof(  md5->state ) );
+
+    SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
+                   sha1->state, sizeof( sha1->state ) );
+
+    if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+    {
+        sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT"
+                                           : (char *) "SRVR";
+
+        memset( padbuf, 0x36, 48 );
+
+        md5_update( md5, (unsigned char *) sender, 4 );
+        md5_update( md5, ssl->session->master, 48 );
+        md5_update( md5, padbuf, 48 );
+        md5_finish( md5, md5sum );
+
+        sha1_update( sha1, (unsigned char *) sender, 4 );
+        sha1_update( sha1, ssl->session->master, 48 );
+        sha1_update( sha1, padbuf, 40 );
+        sha1_finish( sha1, sha1sum );
+
+        memset( padbuf, 0x5C, 48 );
+
+        md5_starts( md5 );
+        md5_update( md5, ssl->session->master, 48 );
+        md5_update( md5, padbuf, 48 );
+        md5_update( md5, md5sum, 16 );
+        md5_finish( md5, buf );
+
+        sha1_starts( sha1 );
+        sha1_update( sha1, ssl->session->master, 48 );
+        sha1_update( sha1, padbuf , 40 );
+        sha1_update( sha1, sha1sum, 20 );
+        sha1_finish( sha1, buf + 16 );
+
+        len += 24;
+    }
+    else
+    {
+        sender = ( from == SSL_IS_CLIENT )
+                 ? (char *) "client finished"
+                 : (char *) "server finished";
+
+         md5_finish(  md5, padbuf );
+        sha1_finish( sha1, padbuf + 16 );
+
+        tls1_prf( ssl->session->master, 48, sender,
+                  padbuf, 36, buf, len );
+    }
+
+    SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+    memset(  md5, 0, sizeof(  md5_context ) );
+    memset( sha1, 0, sizeof( sha1_context ) );
+
+    memset(  padbuf, 0, sizeof(  padbuf ) );
+    memset(  md5sum, 0, sizeof(  md5sum ) );
+    memset( sha1sum, 0, sizeof( sha1sum ) );
+
+    SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
+}
+
+int ssl_write_finished( ssl_context *ssl )
+{
+    int ret, hash_len;
+     md5_context  md5;
+    sha1_context sha1;
+
+    SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
+
+    memcpy( &md5 , &ssl->fin_md5 , sizeof(  md5_context ) );
+    memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) );
+
+    ssl_calc_finished( ssl, ssl->out_msg + 4,
+                       ssl->endpoint, &md5, &sha1 );
+
+    hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+    ssl->out_msglen  = 4 + hash_len;
+    ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = SSL_HS_FINISHED;
+
+    /*
+     * In case of session resuming, invert the client and server
+     * ChangeCipherSpec messages order.
+     */
+    if( ssl->resume != 0 )
+    {
+        if( ssl->endpoint == SSL_IS_CLIENT )
+            ssl->state = SSL_HANDSHAKE_OVER;
+        else
+            ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+    }
+    else
+        ssl->state++;
+
+    ssl->do_crypt = 1;
+
+    if( ( ret = ssl_write_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+        return( ret );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
+
+    return( 0 );
+}
+
+int ssl_parse_finished( ssl_context *ssl )
+{
+    int ret;
+    unsigned int hash_len;
+    unsigned char buf[36];
+    md5_context  md5;
+    sha1_context sha1;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
+
+    memcpy( &md5 , &ssl->fin_md5 , sizeof(  md5_context ) );
+    memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) );
+
+    ssl->do_crypt = 1;
+
+    if( ( ret = ssl_read_record( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+        return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+    if( ssl->in_msg[0] != SSL_HS_FINISHED ||
+        ssl->in_hslen  != 4 + hash_len )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+    }
+
+    ssl_calc_finished( ssl, buf, ssl->endpoint ^ 1, &md5, &sha1 );
+
+    if( memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+    }
+
+    if( ssl->resume != 0 )
+    {
+        if( ssl->endpoint == SSL_IS_CLIENT )
+            ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+
+        if( ssl->endpoint == SSL_IS_SERVER )
+            ssl->state = SSL_HANDSHAKE_OVER;
+    }
+    else
+        ssl->state++;
+
+    SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
+
+    return( 0 );
+}
+
+/*
+ * Initialize an SSL context
+ */
+int ssl_init( ssl_context *ssl )
+{
+    int len = SSL_BUFFER_LEN;
+
+    memset( ssl, 0, sizeof( ssl_context ) );
+
+    ssl->in_ctr = (unsigned char *) malloc( len );
+    ssl->in_hdr = ssl->in_ctr +  8;
+    ssl->in_msg = ssl->in_ctr + 13;
+
+    if( ssl->in_ctr == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+        return( 1 );
+    }
+
+    ssl->out_ctr = (unsigned char *) malloc( len );
+    ssl->out_hdr = ssl->out_ctr +  8;
+    ssl->out_msg = ssl->out_ctr + 13;
+
+    if( ssl->out_ctr == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+        free( ssl-> in_ctr );
+        return( 1 );
+    }
+
+    memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN );
+    memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+
+    ssl->hostname = NULL;
+    ssl->hostname_len = 0;
+
+     md5_starts( &ssl->fin_md5  );
+    sha1_starts( &ssl->fin_sha1 );
+
+    return( 0 );
+}
+
+/*
+ * SSL set accessors
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint )
+{
+    ssl->endpoint   = endpoint;
+}
+
+void ssl_set_authmode( ssl_context *ssl, int authmode )
+{
+    ssl->authmode   = authmode;
+}
+
+void ssl_set_verify( ssl_context *ssl,
+                     int (*f_vrfy)(void *, x509_cert *, int, int),
+                     void *p_vrfy )
+{
+    ssl->f_vrfy      = f_vrfy;
+    ssl->p_vrfy      = p_vrfy;
+}
+
+void ssl_set_rng( ssl_context *ssl,
+                  int (*f_rng)(void *),
+                  void *p_rng )
+{
+    ssl->f_rng      = f_rng;
+    ssl->p_rng      = p_rng;
+}
+
+void ssl_set_dbg( ssl_context *ssl,
+                  void (*f_dbg)(void *, int, const char *),
+                  void  *p_dbg )
+{
+    ssl->f_dbg      = f_dbg;
+    ssl->p_dbg      = p_dbg;
+}
+
+void ssl_set_bio( ssl_context *ssl,
+            int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+            int (*f_send)(void *, const unsigned char *, size_t), void *p_send )
+{
+    ssl->f_recv     = f_recv;
+    ssl->f_send     = f_send;
+    ssl->p_recv     = p_recv;
+    ssl->p_send     = p_send;
+}
+
+void ssl_set_scb( ssl_context *ssl,
+                  int (*s_get)(ssl_context *),
+                  int (*s_set)(ssl_context *) )
+{
+    ssl->s_get      = s_get;
+    ssl->s_set      = s_set;
+}
+
+void ssl_set_session( ssl_context *ssl, int resume, int timeout,
+                      ssl_session *session )
+{
+    ssl->resume     = resume;
+    ssl->timeout    = timeout;
+    ssl->session    = session;
+}
+
+void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites )
+{
+    ssl->ciphersuites    = ciphersuites;
+}
+
+void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+                       x509_crl *ca_crl, const char *peer_cn )
+{
+    ssl->ca_chain   = ca_chain;
+    ssl->ca_crl     = ca_crl;
+    ssl->peer_cn    = peer_cn;
+}
+
+void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+                       rsa_context *rsa_key )
+{
+    ssl->own_cert   = own_cert;
+    ssl->rsa_key    = rsa_key;
+}
+
+#if defined(POLARSSL_PKCS11_C)
+void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert,
+                       pkcs11_context *pkcs11_key )
+{
+    ssl->own_cert   = own_cert;
+    ssl->pkcs11_key = pkcs11_key;
+}
+#endif
+
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G )
+{
+    int ret;
+
+    if( ( ret = mpi_read_string( &ssl->dhm_ctx.P, 16, dhm_P ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+        return( ret );
+    }
+
+    if( ( ret = mpi_read_string( &ssl->dhm_ctx.G, 16, dhm_G ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
+{
+    int ret;
+
+    if( ( ret = mpi_copy(&ssl->dhm_ctx.P, &dhm_ctx->P) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_copy", ret );
+        return( ret );
+    }
+
+    if( ( ret = mpi_copy(&ssl->dhm_ctx.G, &dhm_ctx->G) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "mpi_copy", ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+int ssl_set_hostname( ssl_context *ssl, const char *hostname )
+{
+    if( hostname == NULL )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+    ssl->hostname_len = strlen( hostname );
+    ssl->hostname = (unsigned char *) malloc( ssl->hostname_len + 1 );
+
+    memcpy( ssl->hostname, (unsigned char *) hostname,
+            ssl->hostname_len );
+    
+    ssl->hostname[ssl->hostname_len] = '\0';
+
+    return( 0 );
+}
+
+/*
+ * SSL get accessors
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl )
+{
+    return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
+}
+
+int ssl_get_verify_result( const ssl_context *ssl )
+{
+    return( ssl->verify_result );
+}
+
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id )
+{
+    switch( ciphersuite_id )
+    {
+#if defined(POLARSSL_ARC4_C)
+        case SSL_RSA_RC4_128_MD5:
+            return( "SSL-RSA-RC4-128-MD5" );
+
+        case SSL_RSA_RC4_128_SHA:
+            return( "SSL-RSA-RC4-128-SHA" );
+#endif
+
+#if defined(POLARSSL_DES_C)
+        case SSL_RSA_DES_168_SHA:
+            return( "SSL-RSA-DES-168-SHA" );
+
+        case SSL_EDH_RSA_DES_168_SHA:
+            return( "SSL-EDH-RSA-DES-168-SHA" );
+#endif
+
+#if defined(POLARSSL_AES_C)
+        case SSL_RSA_AES_128_SHA:
+            return( "SSL-RSA-AES-128-SHA" );
+
+        case SSL_EDH_RSA_AES_128_SHA:
+            return( "SSL-EDH-RSA-AES-128-SHA" );
+
+        case SSL_RSA_AES_256_SHA:
+            return( "SSL-RSA-AES-256-SHA" );
+
+        case SSL_EDH_RSA_AES_256_SHA:
+            return( "SSL-EDH-RSA-AES-256-SHA" );
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+        case SSL_RSA_CAMELLIA_128_SHA:
+            return( "SSL-RSA-CAMELLIA-128-SHA" );
+
+        case SSL_EDH_RSA_CAMELLIA_128_SHA:
+            return( "SSL-EDH-RSA-CAMELLIA-128-SHA" );
+
+        case SSL_RSA_CAMELLIA_256_SHA:
+            return( "SSL-RSA-CAMELLIA-256-SHA" );
+
+        case SSL_EDH_RSA_CAMELLIA_256_SHA:
+            return( "SSL-EDH-RSA-CAMELLIA-256-SHA" );
+#endif
+
+    default:
+        break;
+    }
+
+    return( "unknown" );
+}
+
+int ssl_get_ciphersuite_id( const char *ciphersuite_name )
+{
+#if defined(POLARSSL_ARC4_C)
+    if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-MD5"))
+        return( SSL_RSA_RC4_128_MD5 );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-SHA"))
+        return( SSL_RSA_RC4_128_SHA );
+#endif
+
+#if defined(POLARSSL_DES_C)
+    if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-DES-168-SHA"))
+        return( SSL_RSA_DES_168_SHA );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-DES-168-SHA"))
+        return( SSL_EDH_RSA_DES_168_SHA );
+#endif
+
+#if defined(POLARSSL_AES_C)
+    if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-SHA"))
+        return( SSL_RSA_AES_128_SHA );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-SHA"))
+        return( SSL_EDH_RSA_AES_128_SHA );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-SHA"))
+        return( SSL_RSA_AES_256_SHA );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA"))
+        return( SSL_EDH_RSA_AES_256_SHA );
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+    if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-128-SHA"))
+        return( SSL_RSA_CAMELLIA_128_SHA );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-128-SHA"))
+        return( SSL_EDH_RSA_CAMELLIA_128_SHA );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-256-SHA"))
+        return( SSL_RSA_CAMELLIA_256_SHA );
+    if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-256-SHA"))
+        return( SSL_EDH_RSA_CAMELLIA_256_SHA );
+#endif
+
+    return( 0 );
+}
+
+const char *ssl_get_ciphersuite( const ssl_context *ssl )
+{
+    return ssl_get_ciphersuite_name( ssl->session->ciphersuite );
+}
+
+const char *ssl_get_version( const ssl_context *ssl )
+{
+    switch( ssl->minor_ver )
+    {
+        case SSL_MINOR_VERSION_0:
+            return( "SSLv3.0" );
+
+        case SSL_MINOR_VERSION_1:
+            return( "TLSv1.0" );
+
+        case SSL_MINOR_VERSION_2:
+            return( "TLSv1.1" );
+
+        default:
+            break;
+    }
+    return( "unknown" );
+}
+
+int ssl_default_ciphersuites[] =
+{
+#if defined(POLARSSL_DHM_C)
+#if defined(POLARSSL_AES_C)
+    SSL_EDH_RSA_AES_128_SHA,
+    SSL_EDH_RSA_AES_256_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+    SSL_EDH_RSA_CAMELLIA_128_SHA,
+    SSL_EDH_RSA_CAMELLIA_256_SHA,
+#endif
+#if defined(POLARSSL_DES_C)
+    SSL_EDH_RSA_DES_168_SHA,
+#endif
+#endif
+
+#if defined(POLARSSL_AES_C)
+    SSL_RSA_AES_256_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+    SSL_RSA_CAMELLIA_256_SHA,
+#endif
+#if defined(POLARSSL_AES_C)
+    SSL_RSA_AES_128_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+    SSL_RSA_CAMELLIA_128_SHA,
+#endif
+#if defined(POLARSSL_DES_C)
+    SSL_RSA_DES_168_SHA,
+#endif
+#if defined(POLARSSL_ARC4_C)
+    SSL_RSA_RC4_128_SHA,
+    SSL_RSA_RC4_128_MD5,
+#endif
+    0
+};
+
+/*
+ * Perform the SSL handshake
+ */
+int ssl_handshake( ssl_context *ssl )
+{
+    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+    SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
+
+#if defined(POLARSSL_SSL_CLI_C)
+    if( ssl->endpoint == SSL_IS_CLIENT )
+        ret = ssl_handshake_client( ssl );
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C)
+    if( ssl->endpoint == SSL_IS_SERVER )
+        ret = ssl_handshake_server( ssl );
+#endif
+
+    SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
+
+    return( ret );
+}
+
+/*
+ * Receive application data decrypted from the SSL layer
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
+{
+    int ret;
+    size_t n;
+
+    SSL_DEBUG_MSG( 2, ( "=> read" ) );
+
+    if( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        if( ( ret = ssl_handshake( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+            return( ret );
+        }
+    }
+
+    if( ssl->in_offt == NULL )
+    {
+        if( ( ret = ssl_read_record( ssl ) ) != 0 )
+        {
+            if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+                return( 0 );
+
+            SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msglen  == 0 &&
+            ssl->in_msgtype == SSL_MSG_APPLICATION_DATA )
+        {
+            /*
+             * OpenSSL sends empty messages to randomize the IV
+             */
+            if( ( ret = ssl_read_record( ssl ) ) != 0 )
+            {
+                if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+                    return( 0 );
+
+                SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+                return( ret );
+            }
+        }
+
+        if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
+            return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+        }
+
+        ssl->in_offt = ssl->in_msg;
+    }
+
+    n = ( len < ssl->in_msglen )
+        ? len : ssl->in_msglen;
+
+    memcpy( buf, ssl->in_offt, n );
+    ssl->in_msglen -= n;
+
+    if( ssl->in_msglen == 0 )
+        /* all bytes consumed  */
+        ssl->in_offt = NULL;
+    else
+        /* more data available */
+        ssl->in_offt += n;
+
+    SSL_DEBUG_MSG( 2, ( "<= read" ) );
+
+    return( (int) n );
+}
+
+/*
+ * Send application data to be encrypted by the SSL layer
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
+{
+    int ret;
+    size_t n;
+
+    SSL_DEBUG_MSG( 2, ( "=> write" ) );
+
+    if( ssl->state != SSL_HANDSHAKE_OVER )
+    {
+        if( ( ret = ssl_handshake( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+            return( ret );
+        }
+    }
+
+    n = ( len < SSL_MAX_CONTENT_LEN )
+        ? len : SSL_MAX_CONTENT_LEN;
+
+    if( ssl->out_left != 0 )
+    {
+        if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+            return( ret );
+        }
+    }
+    else
+    {
+        ssl->out_msglen  = n;
+        ssl->out_msgtype = SSL_MSG_APPLICATION_DATA;
+        memcpy( ssl->out_msg, buf, n );
+
+        if( ( ret = ssl_write_record( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+            return( ret );
+        }
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write" ) );
+
+    return( (int) n );
+}
+
+/*
+ * Notify the peer that the connection is being closed
+ */
+int ssl_close_notify( ssl_context *ssl )
+{
+    int ret;
+
+    SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
+
+    if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+        return( ret );
+    }
+
+    if( ssl->state == SSL_HANDSHAKE_OVER )
+    {
+        ssl->out_msgtype = SSL_MSG_ALERT;
+        ssl->out_msglen  = 2;
+        ssl->out_msg[0]  = SSL_ALERT_LEVEL_WARNING;
+        ssl->out_msg[1]  = SSL_ALERT_MSG_CLOSE_NOTIFY;
+
+        if( ( ret = ssl_write_record( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+            return( ret );
+        }
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
+
+    return( ret );
+}
+
+/*
+ * Free an SSL context
+ */
+void ssl_free( ssl_context *ssl )
+{
+    SSL_DEBUG_MSG( 2, ( "=> free" ) );
+
+    if( ssl->peer_cert != NULL )
+    {
+        x509_free( ssl->peer_cert );
+        memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
+          free( ssl->peer_cert );
+    }
+
+    if( ssl->out_ctr != NULL )
+    {
+        memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+          free( ssl->out_ctr );
+    }
+
+    if( ssl->in_ctr != NULL )
+    {
+        memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+          free( ssl->in_ctr );
+    }
+
+#if defined(POLARSSL_DHM_C)
+    dhm_free( &ssl->dhm_ctx );
+#endif
+
+    if ( ssl->hostname != NULL)
+    {
+        memset( ssl->hostname, 0, ssl->hostname_len );
+        free( ssl->hostname );
+        ssl->hostname_len = 0;
+    }
+
+    SSL_DEBUG_MSG( 2, ( "<= free" ) );
+
+    /* Actually free after last debug message */
+    memset( ssl, 0, sizeof( ssl_context ) );
+}
+
+#endif

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů