This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

Committer:
ashleymills
Date:
Thu Sep 05 10:33:04 2013 +0000
Revision:
0:714293de3836
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:714293de3836 1 /* asn.c
ashleymills 0:714293de3836 2 *
ashleymills 0:714293de3836 3 * Copyright (C) 2006-2013 wolfSSL Inc.
ashleymills 0:714293de3836 4 *
ashleymills 0:714293de3836 5 * This file is part of CyaSSL.
ashleymills 0:714293de3836 6 *
ashleymills 0:714293de3836 7 * CyaSSL is free software; you can redistribute it and/or modify
ashleymills 0:714293de3836 8 * it under the terms of the GNU General Public License as published by
ashleymills 0:714293de3836 9 * the Free Software Foundation; either version 2 of the License, or
ashleymills 0:714293de3836 10 * (at your option) any later version.
ashleymills 0:714293de3836 11 *
ashleymills 0:714293de3836 12 * CyaSSL is distributed in the hope that it will be useful,
ashleymills 0:714293de3836 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ashleymills 0:714293de3836 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ashleymills 0:714293de3836 15 * GNU General Public License for more details.
ashleymills 0:714293de3836 16 *
ashleymills 0:714293de3836 17 * You should have received a copy of the GNU General Public License
ashleymills 0:714293de3836 18 * along with this program; if not, write to the Free Software
ashleymills 0:714293de3836 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
ashleymills 0:714293de3836 20 */
ashleymills 0:714293de3836 21
ashleymills 0:714293de3836 22 #ifdef HAVE_CONFIG_H
ashleymills 0:714293de3836 23 #include <config.h>
ashleymills 0:714293de3836 24 #endif
ashleymills 0:714293de3836 25
ashleymills 0:714293de3836 26 #include <cyassl/ctaocrypt/settings.h>
ashleymills 0:714293de3836 27
ashleymills 0:714293de3836 28 #ifndef NO_ASN
ashleymills 0:714293de3836 29
ashleymills 0:714293de3836 30 #ifdef HAVE_RTP_SYS
ashleymills 0:714293de3836 31 #include "os.h" /* dc_rtc_api needs */
ashleymills 0:714293de3836 32 #include "dc_rtc_api.h" /* to get current time */
ashleymills 0:714293de3836 33 #endif
ashleymills 0:714293de3836 34
ashleymills 0:714293de3836 35 #include <cyassl/ctaocrypt/integer.h>
ashleymills 0:714293de3836 36 #include <cyassl/ctaocrypt/asn.h>
ashleymills 0:714293de3836 37 #include <cyassl/ctaocrypt/coding.h>
ashleymills 0:714293de3836 38 #include <cyassl/ctaocrypt/sha.h>
ashleymills 0:714293de3836 39 #include <cyassl/ctaocrypt/md5.h>
ashleymills 0:714293de3836 40 #include <cyassl/ctaocrypt/md2.h>
ashleymills 0:714293de3836 41 #include <cyassl/ctaocrypt/ctaoerror2.h>
ashleymills 0:714293de3836 42 #include <cyassl/ctaocrypt/pwdbased.h>
ashleymills 0:714293de3836 43 #include <cyassl/ctaocrypt/des3.h>
ashleymills 0:714293de3836 44 #include <cyassl/ctaocrypt/sha256.h>
ashleymills 0:714293de3836 45 #include <cyassl/ctaocrypt/sha512.h>
ashleymills 0:714293de3836 46 #include <cyassl/ctaocrypt/logging.h>
ashleymills 0:714293de3836 47
ashleymills 0:714293de3836 48 #include <cyassl/ctaocrypt/random.h>
ashleymills 0:714293de3836 49
ashleymills 0:714293de3836 50
ashleymills 0:714293de3836 51 #ifndef NO_RC4
ashleymills 0:714293de3836 52 #include <cyassl/ctaocrypt/arc4.h>
ashleymills 0:714293de3836 53 #endif
ashleymills 0:714293de3836 54
ashleymills 0:714293de3836 55 #ifdef HAVE_NTRU
ashleymills 0:714293de3836 56 #include "crypto_ntru.h"
ashleymills 0:714293de3836 57 #endif
ashleymills 0:714293de3836 58
ashleymills 0:714293de3836 59 #ifdef HAVE_ECC
ashleymills 0:714293de3836 60 #include <cyassl/ctaocrypt/ecc.h>
ashleymills 0:714293de3836 61 #endif
ashleymills 0:714293de3836 62
ashleymills 0:714293de3836 63 #ifdef CYASSL_DEBUG_ENCODING
ashleymills 0:714293de3836 64 #ifdef FREESCALE_MQX
ashleymills 0:714293de3836 65 #include <fio.h>
ashleymills 0:714293de3836 66 #else
ashleymills 0:714293de3836 67 #include <stdio.h>
ashleymills 0:714293de3836 68 #endif
ashleymills 0:714293de3836 69 #endif
ashleymills 0:714293de3836 70
ashleymills 0:714293de3836 71 #ifdef _MSC_VER
ashleymills 0:714293de3836 72 /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
ashleymills 0:714293de3836 73 #pragma warning(disable: 4996)
ashleymills 0:714293de3836 74 #endif
ashleymills 0:714293de3836 75
ashleymills 0:714293de3836 76
ashleymills 0:714293de3836 77 #ifndef TRUE
ashleymills 0:714293de3836 78 #define TRUE 1
ashleymills 0:714293de3836 79 #endif
ashleymills 0:714293de3836 80 #ifndef FALSE
ashleymills 0:714293de3836 81 #define FALSE 0
ashleymills 0:714293de3836 82 #endif
ashleymills 0:714293de3836 83
ashleymills 0:714293de3836 84
ashleymills 0:714293de3836 85 #ifdef HAVE_RTP_SYS
ashleymills 0:714293de3836 86 /* uses parital <time.h> structures */
ashleymills 0:714293de3836 87 #define XTIME(tl) (0)
ashleymills 0:714293de3836 88 #define XGMTIME(c) my_gmtime((c))
ashleymills 0:714293de3836 89 #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
ashleymills 0:714293de3836 90 #elif defined(MICRIUM)
ashleymills 0:714293de3836 91 #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
ashleymills 0:714293de3836 92 #define XVALIDATE_DATE(d,f,t) NetSecure_ValidateDateHandler((d),(f),(t))
ashleymills 0:714293de3836 93 #else
ashleymills 0:714293de3836 94 #define XVALIDATE_DATE(d, f, t) (0)
ashleymills 0:714293de3836 95 #endif
ashleymills 0:714293de3836 96 #define NO_TIME_H
ashleymills 0:714293de3836 97 /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */
ashleymills 0:714293de3836 98 #elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
ashleymills 0:714293de3836 99 #include <time.h>
ashleymills 0:714293de3836 100 #define XTIME(t1) pic32_time((t1))
ashleymills 0:714293de3836 101 #define XGMTIME(c) gmtime((c))
ashleymills 0:714293de3836 102 #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
ashleymills 0:714293de3836 103 #elif defined(CYASSL_MDK_ARM)
ashleymills 0:714293de3836 104 #include <rtl.h>
ashleymills 0:714293de3836 105 #undef RNG
ashleymills 0:714293de3836 106 #include "cyassl_MDK_ARM.h"
ashleymills 0:714293de3836 107 #undef RNG
ashleymills 0:714293de3836 108 #define RNG CyaSSL_RNG /*for avoiding name conflict in "stm32f2xx.h" */
ashleymills 0:714293de3836 109 #define XTIME(tl) (0)
ashleymills 0:714293de3836 110 #define XGMTIME(c) Cyassl_MDK_gmtime((c))
ashleymills 0:714293de3836 111 #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
ashleymills 0:714293de3836 112 #elif defined(USER_TIME)
ashleymills 0:714293de3836 113 /* user time, and gmtime compatible functions, there is a gmtime
ashleymills 0:714293de3836 114 implementation here that WINCE uses, so really just need some ticks
ashleymills 0:714293de3836 115 since the EPOCH
ashleymills 0:714293de3836 116 */
ashleymills 0:714293de3836 117
ashleymills 0:714293de3836 118 struct tm {
ashleymills 0:714293de3836 119 int tm_sec; /* seconds after the minute [0-60] */
ashleymills 0:714293de3836 120 int tm_min; /* minutes after the hour [0-59] */
ashleymills 0:714293de3836 121 int tm_hour; /* hours since midnight [0-23] */
ashleymills 0:714293de3836 122 int tm_mday; /* day of the month [1-31] */
ashleymills 0:714293de3836 123 int tm_mon; /* months since January [0-11] */
ashleymills 0:714293de3836 124 int tm_year; /* years since 1900 */
ashleymills 0:714293de3836 125 int tm_wday; /* days since Sunday [0-6] */
ashleymills 0:714293de3836 126 int tm_yday; /* days since January 1 [0-365] */
ashleymills 0:714293de3836 127 int tm_isdst; /* Daylight Savings Time flag */
ashleymills 0:714293de3836 128 long tm_gmtoff; /* offset from CUT in seconds */
ashleymills 0:714293de3836 129 char *tm_zone; /* timezone abbreviation */
ashleymills 0:714293de3836 130 };
ashleymills 0:714293de3836 131 typedef long time_t;
ashleymills 0:714293de3836 132
ashleymills 0:714293de3836 133 /* forward declaration */
ashleymills 0:714293de3836 134 struct tm* gmtime(const time_t* timer);
ashleymills 0:714293de3836 135 extern time_t XTIME(time_t * timer);
ashleymills 0:714293de3836 136
ashleymills 0:714293de3836 137 #define XGMTIME(c) gmtime((c))
ashleymills 0:714293de3836 138 #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
ashleymills 0:714293de3836 139
ashleymills 0:714293de3836 140 #ifdef STACK_TRAP
ashleymills 0:714293de3836 141 /* for stack trap tracking, don't call os gmtime on OS X/linux,
ashleymills 0:714293de3836 142 uses a lot of stack spce */
ashleymills 0:714293de3836 143 extern time_t time(time_t * timer);
ashleymills 0:714293de3836 144 #define XTIME(tl) time((tl))
ashleymills 0:714293de3836 145 #endif /* STACK_TRAP */
ashleymills 0:714293de3836 146 #else
ashleymills 0:714293de3836 147 /* default */
ashleymills 0:714293de3836 148 /* uses complete <time.h> facility */
ashleymills 0:714293de3836 149 #include <time.h>
ashleymills 0:714293de3836 150 #define XTIME(tl) time((tl))
ashleymills 0:714293de3836 151 #define XGMTIME(c) gmtime((c))
ashleymills 0:714293de3836 152 #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
ashleymills 0:714293de3836 153 #endif
ashleymills 0:714293de3836 154
ashleymills 0:714293de3836 155
ashleymills 0:714293de3836 156 #ifdef _WIN32_WCE
ashleymills 0:714293de3836 157 /* no time() or gmtime() even though in time.h header?? */
ashleymills 0:714293de3836 158
ashleymills 0:714293de3836 159 #include <windows.h>
ashleymills 0:714293de3836 160
ashleymills 0:714293de3836 161
ashleymills 0:714293de3836 162 time_t time(time_t* timer)
ashleymills 0:714293de3836 163 {
ashleymills 0:714293de3836 164 SYSTEMTIME sysTime;
ashleymills 0:714293de3836 165 FILETIME fTime;
ashleymills 0:714293de3836 166 ULARGE_INTEGER intTime;
ashleymills 0:714293de3836 167 time_t localTime;
ashleymills 0:714293de3836 168
ashleymills 0:714293de3836 169 if (timer == NULL)
ashleymills 0:714293de3836 170 timer = &localTime;
ashleymills 0:714293de3836 171
ashleymills 0:714293de3836 172 GetSystemTime(&sysTime);
ashleymills 0:714293de3836 173 SystemTimeToFileTime(&sysTime, &fTime);
ashleymills 0:714293de3836 174
ashleymills 0:714293de3836 175 XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
ashleymills 0:714293de3836 176 /* subtract EPOCH */
ashleymills 0:714293de3836 177 intTime.QuadPart -= 0x19db1ded53e8000;
ashleymills 0:714293de3836 178 /* to secs */
ashleymills 0:714293de3836 179 intTime.QuadPart /= 10000000;
ashleymills 0:714293de3836 180 *timer = (time_t)intTime.QuadPart;
ashleymills 0:714293de3836 181
ashleymills 0:714293de3836 182 return *timer;
ashleymills 0:714293de3836 183 }
ashleymills 0:714293de3836 184
ashleymills 0:714293de3836 185 #endif /* _WIN32_WCE */
ashleymills 0:714293de3836 186 #if defined( _WIN32_WCE ) || defined( USER_TIME )
ashleymills 0:714293de3836 187
ashleymills 0:714293de3836 188 struct tm* gmtime(const time_t* timer)
ashleymills 0:714293de3836 189 {
ashleymills 0:714293de3836 190 #define YEAR0 1900
ashleymills 0:714293de3836 191 #define EPOCH_YEAR 1970
ashleymills 0:714293de3836 192 #define SECS_DAY (24L * 60L * 60L)
ashleymills 0:714293de3836 193 #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
ashleymills 0:714293de3836 194 #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
ashleymills 0:714293de3836 195
ashleymills 0:714293de3836 196 static const int _ytab[2][12] =
ashleymills 0:714293de3836 197 {
ashleymills 0:714293de3836 198 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
ashleymills 0:714293de3836 199 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
ashleymills 0:714293de3836 200 };
ashleymills 0:714293de3836 201
ashleymills 0:714293de3836 202 static struct tm st_time;
ashleymills 0:714293de3836 203 struct tm* ret = &st_time;
ashleymills 0:714293de3836 204 time_t secs = *timer;
ashleymills 0:714293de3836 205 unsigned long dayclock, dayno;
ashleymills 0:714293de3836 206 int year = EPOCH_YEAR;
ashleymills 0:714293de3836 207
ashleymills 0:714293de3836 208 dayclock = (unsigned long)secs % SECS_DAY;
ashleymills 0:714293de3836 209 dayno = (unsigned long)secs / SECS_DAY;
ashleymills 0:714293de3836 210
ashleymills 0:714293de3836 211 ret->tm_sec = (int) dayclock % 60;
ashleymills 0:714293de3836 212 ret->tm_min = (int)(dayclock % 3600) / 60;
ashleymills 0:714293de3836 213 ret->tm_hour = (int) dayclock / 3600;
ashleymills 0:714293de3836 214 ret->tm_wday = (int) (dayno + 4) % 7; /* day 0 a Thursday */
ashleymills 0:714293de3836 215
ashleymills 0:714293de3836 216 while(dayno >= (unsigned long)YEARSIZE(year)) {
ashleymills 0:714293de3836 217 dayno -= YEARSIZE(year);
ashleymills 0:714293de3836 218 year++;
ashleymills 0:714293de3836 219 }
ashleymills 0:714293de3836 220
ashleymills 0:714293de3836 221 ret->tm_year = year - YEAR0;
ashleymills 0:714293de3836 222 ret->tm_yday = (int)dayno;
ashleymills 0:714293de3836 223 ret->tm_mon = 0;
ashleymills 0:714293de3836 224
ashleymills 0:714293de3836 225 while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
ashleymills 0:714293de3836 226 dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
ashleymills 0:714293de3836 227 ret->tm_mon++;
ashleymills 0:714293de3836 228 }
ashleymills 0:714293de3836 229
ashleymills 0:714293de3836 230 ret->tm_mday = (int)++dayno;
ashleymills 0:714293de3836 231 ret->tm_isdst = 0;
ashleymills 0:714293de3836 232
ashleymills 0:714293de3836 233 return ret;
ashleymills 0:714293de3836 234 }
ashleymills 0:714293de3836 235
ashleymills 0:714293de3836 236 #endif /* _WIN32_WCE || USER_TIME */
ashleymills 0:714293de3836 237
ashleymills 0:714293de3836 238
ashleymills 0:714293de3836 239 #ifdef HAVE_RTP_SYS
ashleymills 0:714293de3836 240
ashleymills 0:714293de3836 241 #define YEAR0 1900
ashleymills 0:714293de3836 242
ashleymills 0:714293de3836 243 struct tm* my_gmtime(const time_t* timer) /* has a gmtime() but hangs */
ashleymills 0:714293de3836 244 {
ashleymills 0:714293de3836 245 static struct tm st_time;
ashleymills 0:714293de3836 246 struct tm* ret = &st_time;
ashleymills 0:714293de3836 247
ashleymills 0:714293de3836 248 DC_RTC_CALENDAR cal;
ashleymills 0:714293de3836 249 dc_rtc_time_get(&cal, TRUE);
ashleymills 0:714293de3836 250
ashleymills 0:714293de3836 251 ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */
ashleymills 0:714293de3836 252 ret->tm_mon = cal.month - 1; /* gm starts at 0 */
ashleymills 0:714293de3836 253 ret->tm_mday = cal.day;
ashleymills 0:714293de3836 254 ret->tm_hour = cal.hour;
ashleymills 0:714293de3836 255 ret->tm_min = cal.minute;
ashleymills 0:714293de3836 256 ret->tm_sec = cal.second;
ashleymills 0:714293de3836 257
ashleymills 0:714293de3836 258 return ret;
ashleymills 0:714293de3836 259 }
ashleymills 0:714293de3836 260
ashleymills 0:714293de3836 261 #endif /* HAVE_RTP_SYS */
ashleymills 0:714293de3836 262
ashleymills 0:714293de3836 263
ashleymills 0:714293de3836 264 #if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
ashleymills 0:714293de3836 265
ashleymills 0:714293de3836 266 /*
ashleymills 0:714293de3836 267 * time() is just a stub in Microchip libraries. We need our own
ashleymills 0:714293de3836 268 * implementation. Use SNTP client to get seconds since epoch.
ashleymills 0:714293de3836 269 */
ashleymills 0:714293de3836 270 time_t pic32_time(time_t* timer)
ashleymills 0:714293de3836 271 {
ashleymills 0:714293de3836 272 #ifdef MICROCHIP_TCPIP_V5
ashleymills 0:714293de3836 273 DWORD sec = 0;
ashleymills 0:714293de3836 274 #else
ashleymills 0:714293de3836 275 uint32_t sec = 0;
ashleymills 0:714293de3836 276 #endif
ashleymills 0:714293de3836 277 time_t localTime;
ashleymills 0:714293de3836 278
ashleymills 0:714293de3836 279 if (timer == NULL)
ashleymills 0:714293de3836 280 timer = &localTime;
ashleymills 0:714293de3836 281
ashleymills 0:714293de3836 282 sec = SNTPGetUTCSeconds();
ashleymills 0:714293de3836 283 *timer = (time_t) sec;
ashleymills 0:714293de3836 284
ashleymills 0:714293de3836 285 return *timer;
ashleymills 0:714293de3836 286 }
ashleymills 0:714293de3836 287
ashleymills 0:714293de3836 288 #endif /* MICROCHIP_TCPIP */
ashleymills 0:714293de3836 289
ashleymills 0:714293de3836 290
ashleymills 0:714293de3836 291 static INLINE word32 btoi(byte b)
ashleymills 0:714293de3836 292 {
ashleymills 0:714293de3836 293 return b - 0x30;
ashleymills 0:714293de3836 294 }
ashleymills 0:714293de3836 295
ashleymills 0:714293de3836 296
ashleymills 0:714293de3836 297 /* two byte date/time, add to value */
ashleymills 0:714293de3836 298 static INLINE void GetTime(int* value, const byte* date, int* idx)
ashleymills 0:714293de3836 299 {
ashleymills 0:714293de3836 300 int i = *idx;
ashleymills 0:714293de3836 301
ashleymills 0:714293de3836 302 *value += btoi(date[i++]) * 10;
ashleymills 0:714293de3836 303 *value += btoi(date[i++]);
ashleymills 0:714293de3836 304
ashleymills 0:714293de3836 305 *idx = i;
ashleymills 0:714293de3836 306 }
ashleymills 0:714293de3836 307
ashleymills 0:714293de3836 308
ashleymills 0:714293de3836 309 #if defined(MICRIUM)
ashleymills 0:714293de3836 310
ashleymills 0:714293de3836 311 CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format,
ashleymills 0:714293de3836 312 CPU_INT08U dateType)
ashleymills 0:714293de3836 313 {
ashleymills 0:714293de3836 314 CPU_BOOLEAN rtn_code;
ashleymills 0:714293de3836 315 CPU_INT32S i;
ashleymills 0:714293de3836 316 CPU_INT32S val;
ashleymills 0:714293de3836 317 CPU_INT16U year;
ashleymills 0:714293de3836 318 CPU_INT08U month;
ashleymills 0:714293de3836 319 CPU_INT16U day;
ashleymills 0:714293de3836 320 CPU_INT08U hour;
ashleymills 0:714293de3836 321 CPU_INT08U min;
ashleymills 0:714293de3836 322 CPU_INT08U sec;
ashleymills 0:714293de3836 323
ashleymills 0:714293de3836 324 i = 0;
ashleymills 0:714293de3836 325 year = 0u;
ashleymills 0:714293de3836 326
ashleymills 0:714293de3836 327 if (format == ASN_UTC_TIME) {
ashleymills 0:714293de3836 328 if (btoi(date[0]) >= 5)
ashleymills 0:714293de3836 329 year = 1900;
ashleymills 0:714293de3836 330 else
ashleymills 0:714293de3836 331 year = 2000;
ashleymills 0:714293de3836 332 }
ashleymills 0:714293de3836 333 else { /* format == GENERALIZED_TIME */
ashleymills 0:714293de3836 334 year += btoi(date[i++]) * 1000;
ashleymills 0:714293de3836 335 year += btoi(date[i++]) * 100;
ashleymills 0:714293de3836 336 }
ashleymills 0:714293de3836 337
ashleymills 0:714293de3836 338 val = year;
ashleymills 0:714293de3836 339 GetTime(&val, date, &i);
ashleymills 0:714293de3836 340 year = (CPU_INT16U)val;
ashleymills 0:714293de3836 341
ashleymills 0:714293de3836 342 val = 0;
ashleymills 0:714293de3836 343 GetTime(&val, date, &i);
ashleymills 0:714293de3836 344 month = (CPU_INT08U)val;
ashleymills 0:714293de3836 345
ashleymills 0:714293de3836 346 val = 0;
ashleymills 0:714293de3836 347 GetTime(&val, date, &i);
ashleymills 0:714293de3836 348 day = (CPU_INT16U)val;
ashleymills 0:714293de3836 349
ashleymills 0:714293de3836 350 val = 0;
ashleymills 0:714293de3836 351 GetTime(&val, date, &i);
ashleymills 0:714293de3836 352 hour = (CPU_INT08U)val;
ashleymills 0:714293de3836 353
ashleymills 0:714293de3836 354 val = 0;
ashleymills 0:714293de3836 355 GetTime(&val, date, &i);
ashleymills 0:714293de3836 356 min = (CPU_INT08U)val;
ashleymills 0:714293de3836 357
ashleymills 0:714293de3836 358 val = 0;
ashleymills 0:714293de3836 359 GetTime(&val, date, &i);
ashleymills 0:714293de3836 360 sec = (CPU_INT08U)val;
ashleymills 0:714293de3836 361
ashleymills 0:714293de3836 362 return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType);
ashleymills 0:714293de3836 363 }
ashleymills 0:714293de3836 364
ashleymills 0:714293de3836 365 #endif /* MICRIUM */
ashleymills 0:714293de3836 366
ashleymills 0:714293de3836 367
ashleymills 0:714293de3836 368 static int GetLength(const byte* input, word32* inOutIdx, int* len,
ashleymills 0:714293de3836 369 word32 maxIdx)
ashleymills 0:714293de3836 370 {
ashleymills 0:714293de3836 371 int length = 0;
ashleymills 0:714293de3836 372 word32 i = *inOutIdx;
ashleymills 0:714293de3836 373 byte b;
ashleymills 0:714293de3836 374
ashleymills 0:714293de3836 375 if ( (i+1) > maxIdx) { /* for first read */
ashleymills 0:714293de3836 376 CYASSL_MSG("GetLength bad index on input");
ashleymills 0:714293de3836 377 return BUFFER_E;
ashleymills 0:714293de3836 378 }
ashleymills 0:714293de3836 379
ashleymills 0:714293de3836 380 b = input[i++];
ashleymills 0:714293de3836 381 if (b >= ASN_LONG_LENGTH) {
ashleymills 0:714293de3836 382 word32 bytes = b & 0x7F;
ashleymills 0:714293de3836 383
ashleymills 0:714293de3836 384 if ( (i+bytes) > maxIdx) { /* for reading bytes */
ashleymills 0:714293de3836 385 CYASSL_MSG("GetLength bad long length");
ashleymills 0:714293de3836 386 return BUFFER_E;
ashleymills 0:714293de3836 387 }
ashleymills 0:714293de3836 388
ashleymills 0:714293de3836 389 while (bytes--) {
ashleymills 0:714293de3836 390 b = input[i++];
ashleymills 0:714293de3836 391 length = (length << 8) | b;
ashleymills 0:714293de3836 392 }
ashleymills 0:714293de3836 393 }
ashleymills 0:714293de3836 394 else
ashleymills 0:714293de3836 395 length = b;
ashleymills 0:714293de3836 396
ashleymills 0:714293de3836 397 if ( (i+length) > maxIdx) { /* for user of length */
ashleymills 0:714293de3836 398 CYASSL_MSG("GetLength value exceeds buffer length");
ashleymills 0:714293de3836 399 return BUFFER_E;
ashleymills 0:714293de3836 400 }
ashleymills 0:714293de3836 401
ashleymills 0:714293de3836 402 *inOutIdx = i;
ashleymills 0:714293de3836 403 *len = length;
ashleymills 0:714293de3836 404
ashleymills 0:714293de3836 405 return length;
ashleymills 0:714293de3836 406 }
ashleymills 0:714293de3836 407
ashleymills 0:714293de3836 408
ashleymills 0:714293de3836 409 static int GetSequence(const byte* input, word32* inOutIdx, int* len,
ashleymills 0:714293de3836 410 word32 maxIdx)
ashleymills 0:714293de3836 411 {
ashleymills 0:714293de3836 412 int length = -1;
ashleymills 0:714293de3836 413 word32 idx = *inOutIdx;
ashleymills 0:714293de3836 414
ashleymills 0:714293de3836 415 if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
ashleymills 0:714293de3836 416 GetLength(input, &idx, &length, maxIdx) < 0)
ashleymills 0:714293de3836 417 return ASN_PARSE_E;
ashleymills 0:714293de3836 418
ashleymills 0:714293de3836 419 *len = length;
ashleymills 0:714293de3836 420 *inOutIdx = idx;
ashleymills 0:714293de3836 421
ashleymills 0:714293de3836 422 return length;
ashleymills 0:714293de3836 423 }
ashleymills 0:714293de3836 424
ashleymills 0:714293de3836 425
ashleymills 0:714293de3836 426 static int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx)
ashleymills 0:714293de3836 427 {
ashleymills 0:714293de3836 428 int length = -1;
ashleymills 0:714293de3836 429 word32 idx = *inOutIdx;
ashleymills 0:714293de3836 430
ashleymills 0:714293de3836 431 if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) ||
ashleymills 0:714293de3836 432 GetLength(input, &idx, &length, maxIdx) < 0)
ashleymills 0:714293de3836 433 return ASN_PARSE_E;
ashleymills 0:714293de3836 434
ashleymills 0:714293de3836 435 *len = length;
ashleymills 0:714293de3836 436 *inOutIdx = idx;
ashleymills 0:714293de3836 437
ashleymills 0:714293de3836 438 return length;
ashleymills 0:714293de3836 439 }
ashleymills 0:714293de3836 440
ashleymills 0:714293de3836 441
ashleymills 0:714293de3836 442 /* winodws header clash for WinCE using GetVersion */
ashleymills 0:714293de3836 443 static int GetMyVersion(const byte* input, word32* inOutIdx, int* version)
ashleymills 0:714293de3836 444 {
ashleymills 0:714293de3836 445 word32 idx = *inOutIdx;
ashleymills 0:714293de3836 446
ashleymills 0:714293de3836 447 CYASSL_ENTER("GetMyVersion");
ashleymills 0:714293de3836 448
ashleymills 0:714293de3836 449 if (input[idx++] != ASN_INTEGER)
ashleymills 0:714293de3836 450 return ASN_PARSE_E;
ashleymills 0:714293de3836 451
ashleymills 0:714293de3836 452 if (input[idx++] != 0x01)
ashleymills 0:714293de3836 453 return ASN_VERSION_E;
ashleymills 0:714293de3836 454
ashleymills 0:714293de3836 455 *version = input[idx++];
ashleymills 0:714293de3836 456 *inOutIdx = idx;
ashleymills 0:714293de3836 457
ashleymills 0:714293de3836 458 return *version;
ashleymills 0:714293de3836 459 }
ashleymills 0:714293de3836 460
ashleymills 0:714293de3836 461
ashleymills 0:714293de3836 462 #ifndef NO_PWDBASED
ashleymills 0:714293de3836 463 /* Get small count integer, 32 bits or less */
ashleymills 0:714293de3836 464 static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
ashleymills 0:714293de3836 465 {
ashleymills 0:714293de3836 466 word32 idx = *inOutIdx;
ashleymills 0:714293de3836 467 word32 len;
ashleymills 0:714293de3836 468
ashleymills 0:714293de3836 469 *number = 0;
ashleymills 0:714293de3836 470
ashleymills 0:714293de3836 471 if (input[idx++] != ASN_INTEGER)
ashleymills 0:714293de3836 472 return ASN_PARSE_E;
ashleymills 0:714293de3836 473
ashleymills 0:714293de3836 474 len = input[idx++];
ashleymills 0:714293de3836 475 if (len > 4)
ashleymills 0:714293de3836 476 return ASN_PARSE_E;
ashleymills 0:714293de3836 477
ashleymills 0:714293de3836 478 while (len--) {
ashleymills 0:714293de3836 479 *number = *number << 8 | input[idx++];
ashleymills 0:714293de3836 480 }
ashleymills 0:714293de3836 481
ashleymills 0:714293de3836 482 *inOutIdx = idx;
ashleymills 0:714293de3836 483
ashleymills 0:714293de3836 484 return *number;
ashleymills 0:714293de3836 485 }
ashleymills 0:714293de3836 486 #endif /* !NO_PWDBASED */
ashleymills 0:714293de3836 487
ashleymills 0:714293de3836 488
ashleymills 0:714293de3836 489 /* May not have one, not an error */
ashleymills 0:714293de3836 490 static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
ashleymills 0:714293de3836 491 {
ashleymills 0:714293de3836 492 word32 idx = *inOutIdx;
ashleymills 0:714293de3836 493
ashleymills 0:714293de3836 494 CYASSL_ENTER("GetExplicitVersion");
ashleymills 0:714293de3836 495 if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
ashleymills 0:714293de3836 496 *inOutIdx = ++idx; /* eat header */
ashleymills 0:714293de3836 497 return GetMyVersion(input, inOutIdx, version);
ashleymills 0:714293de3836 498 }
ashleymills 0:714293de3836 499
ashleymills 0:714293de3836 500 /* go back as is */
ashleymills 0:714293de3836 501 *version = 0;
ashleymills 0:714293de3836 502
ashleymills 0:714293de3836 503 return 0;
ashleymills 0:714293de3836 504 }
ashleymills 0:714293de3836 505
ashleymills 0:714293de3836 506
ashleymills 0:714293de3836 507 static int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
ashleymills 0:714293de3836 508 word32 maxIdx)
ashleymills 0:714293de3836 509 {
ashleymills 0:714293de3836 510 word32 i = *inOutIdx;
ashleymills 0:714293de3836 511 byte b = input[i++];
ashleymills 0:714293de3836 512 int length;
ashleymills 0:714293de3836 513
ashleymills 0:714293de3836 514 if (b != ASN_INTEGER)
ashleymills 0:714293de3836 515 return ASN_PARSE_E;
ashleymills 0:714293de3836 516
ashleymills 0:714293de3836 517 if (GetLength(input, &i, &length, maxIdx) < 0)
ashleymills 0:714293de3836 518 return ASN_PARSE_E;
ashleymills 0:714293de3836 519
ashleymills 0:714293de3836 520 if ( (b = input[i++]) == 0x00)
ashleymills 0:714293de3836 521 length--;
ashleymills 0:714293de3836 522 else
ashleymills 0:714293de3836 523 i--;
ashleymills 0:714293de3836 524
ashleymills 0:714293de3836 525 if (mp_init(mpi) != MP_OKAY)
ashleymills 0:714293de3836 526 return MP_INIT_E;
ashleymills 0:714293de3836 527
ashleymills 0:714293de3836 528 if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) {
ashleymills 0:714293de3836 529 mp_clear(mpi);
ashleymills 0:714293de3836 530 return ASN_GETINT_E;
ashleymills 0:714293de3836 531 }
ashleymills 0:714293de3836 532
ashleymills 0:714293de3836 533 *inOutIdx = i + length;
ashleymills 0:714293de3836 534 return 0;
ashleymills 0:714293de3836 535 }
ashleymills 0:714293de3836 536
ashleymills 0:714293de3836 537
ashleymills 0:714293de3836 538 static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
ashleymills 0:714293de3836 539 word32 maxIdx)
ashleymills 0:714293de3836 540 {
ashleymills 0:714293de3836 541 int length;
ashleymills 0:714293de3836 542 word32 i = *inOutIdx;
ashleymills 0:714293de3836 543 byte b;
ashleymills 0:714293de3836 544 *oid = 0;
ashleymills 0:714293de3836 545
ashleymills 0:714293de3836 546 b = input[i++];
ashleymills 0:714293de3836 547 if (b != ASN_OBJECT_ID)
ashleymills 0:714293de3836 548 return ASN_OBJECT_ID_E;
ashleymills 0:714293de3836 549
ashleymills 0:714293de3836 550 if (GetLength(input, &i, &length, maxIdx) < 0)
ashleymills 0:714293de3836 551 return ASN_PARSE_E;
ashleymills 0:714293de3836 552
ashleymills 0:714293de3836 553 while(length--)
ashleymills 0:714293de3836 554 *oid += input[i++];
ashleymills 0:714293de3836 555 /* just sum it up for now */
ashleymills 0:714293de3836 556
ashleymills 0:714293de3836 557 *inOutIdx = i;
ashleymills 0:714293de3836 558
ashleymills 0:714293de3836 559 return 0;
ashleymills 0:714293de3836 560 }
ashleymills 0:714293de3836 561
ashleymills 0:714293de3836 562
ashleymills 0:714293de3836 563 static int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
ashleymills 0:714293de3836 564 word32 maxIdx)
ashleymills 0:714293de3836 565 {
ashleymills 0:714293de3836 566 int length;
ashleymills 0:714293de3836 567 word32 i = *inOutIdx;
ashleymills 0:714293de3836 568 byte b;
ashleymills 0:714293de3836 569 *oid = 0;
ashleymills 0:714293de3836 570
ashleymills 0:714293de3836 571 CYASSL_ENTER("GetAlgoId");
ashleymills 0:714293de3836 572
ashleymills 0:714293de3836 573 if (GetSequence(input, &i, &length, maxIdx) < 0)
ashleymills 0:714293de3836 574 return ASN_PARSE_E;
ashleymills 0:714293de3836 575
ashleymills 0:714293de3836 576 b = input[i++];
ashleymills 0:714293de3836 577 if (b != ASN_OBJECT_ID)
ashleymills 0:714293de3836 578 return ASN_OBJECT_ID_E;
ashleymills 0:714293de3836 579
ashleymills 0:714293de3836 580 if (GetLength(input, &i, &length, maxIdx) < 0)
ashleymills 0:714293de3836 581 return ASN_PARSE_E;
ashleymills 0:714293de3836 582
ashleymills 0:714293de3836 583 while(length--) {
ashleymills 0:714293de3836 584 /* odd HC08 compiler behavior here when input[i++] */
ashleymills 0:714293de3836 585 *oid += input[i];
ashleymills 0:714293de3836 586 i++;
ashleymills 0:714293de3836 587 }
ashleymills 0:714293de3836 588 /* just sum it up for now */
ashleymills 0:714293de3836 589
ashleymills 0:714293de3836 590 /* could have NULL tag and 0 terminator, but may not */
ashleymills 0:714293de3836 591 b = input[i++];
ashleymills 0:714293de3836 592
ashleymills 0:714293de3836 593 if (b == ASN_TAG_NULL) {
ashleymills 0:714293de3836 594 b = input[i++];
ashleymills 0:714293de3836 595 if (b != 0)
ashleymills 0:714293de3836 596 return ASN_EXPECT_0_E;
ashleymills 0:714293de3836 597 }
ashleymills 0:714293de3836 598 else
ashleymills 0:714293de3836 599 /* go back, didn't have it */
ashleymills 0:714293de3836 600 i--;
ashleymills 0:714293de3836 601
ashleymills 0:714293de3836 602 *inOutIdx = i;
ashleymills 0:714293de3836 603
ashleymills 0:714293de3836 604 return 0;
ashleymills 0:714293de3836 605 }
ashleymills 0:714293de3836 606
ashleymills 0:714293de3836 607 #ifndef NO_RSA
ashleymills 0:714293de3836 608
ashleymills 0:714293de3836 609
ashleymills 0:714293de3836 610 #ifdef HAVE_CAVIUM
ashleymills 0:714293de3836 611
ashleymills 0:714293de3836 612 static int GetCaviumInt(byte** buff, word16* buffSz, const byte* input,
ashleymills 0:714293de3836 613 word32* inOutIdx, word32 maxIdx, void* heap)
ashleymills 0:714293de3836 614 {
ashleymills 0:714293de3836 615 word32 i = *inOutIdx;
ashleymills 0:714293de3836 616 byte b = input[i++];
ashleymills 0:714293de3836 617 int length;
ashleymills 0:714293de3836 618
ashleymills 0:714293de3836 619 if (b != ASN_INTEGER)
ashleymills 0:714293de3836 620 return ASN_PARSE_E;
ashleymills 0:714293de3836 621
ashleymills 0:714293de3836 622 if (GetLength(input, &i, &length, maxIdx) < 0)
ashleymills 0:714293de3836 623 return ASN_PARSE_E;
ashleymills 0:714293de3836 624
ashleymills 0:714293de3836 625 if ( (b = input[i++]) == 0x00)
ashleymills 0:714293de3836 626 length--;
ashleymills 0:714293de3836 627 else
ashleymills 0:714293de3836 628 i--;
ashleymills 0:714293de3836 629
ashleymills 0:714293de3836 630 *buffSz = (word16)length;
ashleymills 0:714293de3836 631 *buff = XMALLOC(*buffSz, heap, DYNAMIC_TYPE_CAVIUM_RSA);
ashleymills 0:714293de3836 632 if (*buff == NULL)
ashleymills 0:714293de3836 633 return MEMORY_E;
ashleymills 0:714293de3836 634
ashleymills 0:714293de3836 635 XMEMCPY(*buff, input + i, *buffSz);
ashleymills 0:714293de3836 636
ashleymills 0:714293de3836 637 *inOutIdx = i + length;
ashleymills 0:714293de3836 638 return 0;
ashleymills 0:714293de3836 639 }
ashleymills 0:714293de3836 640
ashleymills 0:714293de3836 641 static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
ashleymills 0:714293de3836 642 RsaKey* key, word32 inSz)
ashleymills 0:714293de3836 643 {
ashleymills 0:714293de3836 644 int version, length;
ashleymills 0:714293de3836 645 void* h = key->heap;
ashleymills 0:714293de3836 646
ashleymills 0:714293de3836 647 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 648 return ASN_PARSE_E;
ashleymills 0:714293de3836 649
ashleymills 0:714293de3836 650 if (GetMyVersion(input, inOutIdx, &version) < 0)
ashleymills 0:714293de3836 651 return ASN_PARSE_E;
ashleymills 0:714293de3836 652
ashleymills 0:714293de3836 653 key->type = RSA_PRIVATE;
ashleymills 0:714293de3836 654
ashleymills 0:714293de3836 655 if (GetCaviumInt(&key->c_n, &key->c_nSz, input, inOutIdx, inSz, h) < 0 ||
ashleymills 0:714293de3836 656 GetCaviumInt(&key->c_e, &key->c_eSz, input, inOutIdx, inSz, h) < 0 ||
ashleymills 0:714293de3836 657 GetCaviumInt(&key->c_d, &key->c_dSz, input, inOutIdx, inSz, h) < 0 ||
ashleymills 0:714293de3836 658 GetCaviumInt(&key->c_p, &key->c_pSz, input, inOutIdx, inSz, h) < 0 ||
ashleymills 0:714293de3836 659 GetCaviumInt(&key->c_q, &key->c_qSz, input, inOutIdx, inSz, h) < 0 ||
ashleymills 0:714293de3836 660 GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 ||
ashleymills 0:714293de3836 661 GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 ||
ashleymills 0:714293de3836 662 GetCaviumInt(&key->c_u, &key->c_uSz, input, inOutIdx, inSz, h) < 0 )
ashleymills 0:714293de3836 663 return ASN_RSA_KEY_E;
ashleymills 0:714293de3836 664
ashleymills 0:714293de3836 665 return 0;
ashleymills 0:714293de3836 666 }
ashleymills 0:714293de3836 667
ashleymills 0:714293de3836 668
ashleymills 0:714293de3836 669 #endif /* HAVE_CAVIUM */
ashleymills 0:714293de3836 670
ashleymills 0:714293de3836 671 int RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
ashleymills 0:714293de3836 672 word32 inSz)
ashleymills 0:714293de3836 673 {
ashleymills 0:714293de3836 674 int version, length;
ashleymills 0:714293de3836 675
ashleymills 0:714293de3836 676 #ifdef HAVE_CAVIUM
ashleymills 0:714293de3836 677 if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
ashleymills 0:714293de3836 678 return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz);
ashleymills 0:714293de3836 679 #endif
ashleymills 0:714293de3836 680
ashleymills 0:714293de3836 681 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 682 return ASN_PARSE_E;
ashleymills 0:714293de3836 683
ashleymills 0:714293de3836 684 if (GetMyVersion(input, inOutIdx, &version) < 0)
ashleymills 0:714293de3836 685 return ASN_PARSE_E;
ashleymills 0:714293de3836 686
ashleymills 0:714293de3836 687 key->type = RSA_PRIVATE;
ashleymills 0:714293de3836 688
ashleymills 0:714293de3836 689 if (GetInt(&key->n, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 690 GetInt(&key->e, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 691 GetInt(&key->d, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 692 GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 693 GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 694 GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 695 GetInt(&key->dQ, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 696 GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
ashleymills 0:714293de3836 697
ashleymills 0:714293de3836 698 return 0;
ashleymills 0:714293de3836 699 }
ashleymills 0:714293de3836 700
ashleymills 0:714293de3836 701 #endif /* NO_RSA */
ashleymills 0:714293de3836 702
ashleymills 0:714293de3836 703 /* Remove PKCS8 header, move beginning of traditional to beginning of input */
ashleymills 0:714293de3836 704 int ToTraditional(byte* input, word32 sz)
ashleymills 0:714293de3836 705 {
ashleymills 0:714293de3836 706 word32 inOutIdx = 0, oid;
ashleymills 0:714293de3836 707 int version, length;
ashleymills 0:714293de3836 708
ashleymills 0:714293de3836 709 if (GetSequence(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 710 return ASN_PARSE_E;
ashleymills 0:714293de3836 711
ashleymills 0:714293de3836 712 if (GetMyVersion(input, &inOutIdx, &version) < 0)
ashleymills 0:714293de3836 713 return ASN_PARSE_E;
ashleymills 0:714293de3836 714
ashleymills 0:714293de3836 715 if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
ashleymills 0:714293de3836 716 return ASN_PARSE_E;
ashleymills 0:714293de3836 717
ashleymills 0:714293de3836 718 if (input[inOutIdx] == ASN_OBJECT_ID) {
ashleymills 0:714293de3836 719 /* pkcs8 ecc uses slightly different format */
ashleymills 0:714293de3836 720 inOutIdx++; /* past id */
ashleymills 0:714293de3836 721 if (GetLength(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 722 return ASN_PARSE_E;
ashleymills 0:714293de3836 723 inOutIdx += length; /* over sub id, key input will verify */
ashleymills 0:714293de3836 724 }
ashleymills 0:714293de3836 725
ashleymills 0:714293de3836 726 if (input[inOutIdx++] != ASN_OCTET_STRING)
ashleymills 0:714293de3836 727 return ASN_PARSE_E;
ashleymills 0:714293de3836 728
ashleymills 0:714293de3836 729 if (GetLength(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 730 return ASN_PARSE_E;
ashleymills 0:714293de3836 731
ashleymills 0:714293de3836 732 XMEMMOVE(input, input + inOutIdx, length);
ashleymills 0:714293de3836 733
ashleymills 0:714293de3836 734 return 0;
ashleymills 0:714293de3836 735 }
ashleymills 0:714293de3836 736
ashleymills 0:714293de3836 737
ashleymills 0:714293de3836 738 #ifndef NO_PWDBASED
ashleymills 0:714293de3836 739
ashleymills 0:714293de3836 740 /* Check To see if PKCS version algo is supported, set id if it is return 0
ashleymills 0:714293de3836 741 < 0 on error */
ashleymills 0:714293de3836 742 static int CheckAlgo(int first, int second, int* id, int* version)
ashleymills 0:714293de3836 743 {
ashleymills 0:714293de3836 744 *id = ALGO_ID_E;
ashleymills 0:714293de3836 745 *version = PKCS5; /* default */
ashleymills 0:714293de3836 746
ashleymills 0:714293de3836 747 if (first == 1) {
ashleymills 0:714293de3836 748 switch (second) {
ashleymills 0:714293de3836 749 case 1:
ashleymills 0:714293de3836 750 *id = PBE_SHA1_RC4_128;
ashleymills 0:714293de3836 751 *version = PKCS12;
ashleymills 0:714293de3836 752 return 0;
ashleymills 0:714293de3836 753 case 3:
ashleymills 0:714293de3836 754 *id = PBE_SHA1_DES3;
ashleymills 0:714293de3836 755 *version = PKCS12;
ashleymills 0:714293de3836 756 return 0;
ashleymills 0:714293de3836 757 default:
ashleymills 0:714293de3836 758 return ALGO_ID_E;
ashleymills 0:714293de3836 759 }
ashleymills 0:714293de3836 760 }
ashleymills 0:714293de3836 761
ashleymills 0:714293de3836 762 if (first != PKCS5)
ashleymills 0:714293de3836 763 return ASN_INPUT_E; /* VERSION ERROR */
ashleymills 0:714293de3836 764
ashleymills 0:714293de3836 765 if (second == PBES2) {
ashleymills 0:714293de3836 766 *version = PKCS5v2;
ashleymills 0:714293de3836 767 return 0;
ashleymills 0:714293de3836 768 }
ashleymills 0:714293de3836 769
ashleymills 0:714293de3836 770 switch (second) {
ashleymills 0:714293de3836 771 case 3: /* see RFC 2898 for ids */
ashleymills 0:714293de3836 772 *id = PBE_MD5_DES;
ashleymills 0:714293de3836 773 return 0;
ashleymills 0:714293de3836 774 case 10:
ashleymills 0:714293de3836 775 *id = PBE_SHA1_DES;
ashleymills 0:714293de3836 776 return 0;
ashleymills 0:714293de3836 777 default:
ashleymills 0:714293de3836 778 return ALGO_ID_E;
ashleymills 0:714293de3836 779
ashleymills 0:714293de3836 780 }
ashleymills 0:714293de3836 781 }
ashleymills 0:714293de3836 782
ashleymills 0:714293de3836 783
ashleymills 0:714293de3836 784 /* Check To see if PKCS v2 algo is supported, set id if it is return 0
ashleymills 0:714293de3836 785 < 0 on error */
ashleymills 0:714293de3836 786 static int CheckAlgoV2(int oid, int* id)
ashleymills 0:714293de3836 787 {
ashleymills 0:714293de3836 788 switch (oid) {
ashleymills 0:714293de3836 789 case 69:
ashleymills 0:714293de3836 790 *id = PBE_SHA1_DES;
ashleymills 0:714293de3836 791 return 0;
ashleymills 0:714293de3836 792 case 652:
ashleymills 0:714293de3836 793 *id = PBE_SHA1_DES3;
ashleymills 0:714293de3836 794 return 0;
ashleymills 0:714293de3836 795 default:
ashleymills 0:714293de3836 796 return ALGO_ID_E;
ashleymills 0:714293de3836 797
ashleymills 0:714293de3836 798 }
ashleymills 0:714293de3836 799 }
ashleymills 0:714293de3836 800
ashleymills 0:714293de3836 801
ashleymills 0:714293de3836 802 /* Decrypt intput in place from parameters based on id */
ashleymills 0:714293de3836 803 static int DecryptKey(const char* password, int passwordSz, byte* salt,
ashleymills 0:714293de3836 804 int saltSz, int iterations, int id, byte* input,
ashleymills 0:714293de3836 805 int length, int version, byte* cbcIv)
ashleymills 0:714293de3836 806 {
ashleymills 0:714293de3836 807 byte key[MAX_KEY_SIZE];
ashleymills 0:714293de3836 808 int typeH;
ashleymills 0:714293de3836 809 int derivedLen;
ashleymills 0:714293de3836 810 int decryptionType;
ashleymills 0:714293de3836 811 int ret = 0;
ashleymills 0:714293de3836 812
ashleymills 0:714293de3836 813 switch (id) {
ashleymills 0:714293de3836 814 case PBE_MD5_DES:
ashleymills 0:714293de3836 815 typeH = MD5;
ashleymills 0:714293de3836 816 derivedLen = 16; /* may need iv for v1.5 */
ashleymills 0:714293de3836 817 decryptionType = DES_TYPE;
ashleymills 0:714293de3836 818 break;
ashleymills 0:714293de3836 819
ashleymills 0:714293de3836 820 case PBE_SHA1_DES:
ashleymills 0:714293de3836 821 typeH = SHA;
ashleymills 0:714293de3836 822 derivedLen = 16; /* may need iv for v1.5 */
ashleymills 0:714293de3836 823 decryptionType = DES_TYPE;
ashleymills 0:714293de3836 824 break;
ashleymills 0:714293de3836 825
ashleymills 0:714293de3836 826 case PBE_SHA1_DES3:
ashleymills 0:714293de3836 827 typeH = SHA;
ashleymills 0:714293de3836 828 derivedLen = 32; /* may need iv for v1.5 */
ashleymills 0:714293de3836 829 decryptionType = DES3_TYPE;
ashleymills 0:714293de3836 830 break;
ashleymills 0:714293de3836 831
ashleymills 0:714293de3836 832 case PBE_SHA1_RC4_128:
ashleymills 0:714293de3836 833 typeH = SHA;
ashleymills 0:714293de3836 834 derivedLen = 16;
ashleymills 0:714293de3836 835 decryptionType = RC4_TYPE;
ashleymills 0:714293de3836 836 break;
ashleymills 0:714293de3836 837
ashleymills 0:714293de3836 838 default:
ashleymills 0:714293de3836 839 return ALGO_ID_E;
ashleymills 0:714293de3836 840 }
ashleymills 0:714293de3836 841
ashleymills 0:714293de3836 842 if (version == PKCS5v2)
ashleymills 0:714293de3836 843 ret = PBKDF2(key, (byte*)password, passwordSz, salt, saltSz, iterations,
ashleymills 0:714293de3836 844 derivedLen, typeH);
ashleymills 0:714293de3836 845 else if (version == PKCS5)
ashleymills 0:714293de3836 846 ret = PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations,
ashleymills 0:714293de3836 847 derivedLen, typeH);
ashleymills 0:714293de3836 848 else if (version == PKCS12) {
ashleymills 0:714293de3836 849 int i, idx = 0;
ashleymills 0:714293de3836 850 byte unicodePasswd[MAX_UNICODE_SZ];
ashleymills 0:714293de3836 851
ashleymills 0:714293de3836 852 if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd))
ashleymills 0:714293de3836 853 return UNICODE_SIZE_E;
ashleymills 0:714293de3836 854
ashleymills 0:714293de3836 855 for (i = 0; i < passwordSz; i++) {
ashleymills 0:714293de3836 856 unicodePasswd[idx++] = 0x00;
ashleymills 0:714293de3836 857 unicodePasswd[idx++] = (byte)password[i];
ashleymills 0:714293de3836 858 }
ashleymills 0:714293de3836 859 /* add trailing NULL */
ashleymills 0:714293de3836 860 unicodePasswd[idx++] = 0x00;
ashleymills 0:714293de3836 861 unicodePasswd[idx++] = 0x00;
ashleymills 0:714293de3836 862
ashleymills 0:714293de3836 863 ret = PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz,
ashleymills 0:714293de3836 864 iterations, derivedLen, typeH, 1);
ashleymills 0:714293de3836 865 if (decryptionType != RC4_TYPE)
ashleymills 0:714293de3836 866 ret += PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz,
ashleymills 0:714293de3836 867 iterations, 8, typeH, 2);
ashleymills 0:714293de3836 868 }
ashleymills 0:714293de3836 869 else
ashleymills 0:714293de3836 870 return ALGO_ID_E;
ashleymills 0:714293de3836 871
ashleymills 0:714293de3836 872 if (ret != 0)
ashleymills 0:714293de3836 873 return ret;
ashleymills 0:714293de3836 874
ashleymills 0:714293de3836 875 switch (decryptionType) {
ashleymills 0:714293de3836 876 #ifndef NO_DES3
ashleymills 0:714293de3836 877 case DES_TYPE:
ashleymills 0:714293de3836 878 {
ashleymills 0:714293de3836 879 Des dec;
ashleymills 0:714293de3836 880 byte* desIv = key + 8;
ashleymills 0:714293de3836 881
ashleymills 0:714293de3836 882 if (version == PKCS5v2 || version == PKCS12)
ashleymills 0:714293de3836 883 desIv = cbcIv;
ashleymills 0:714293de3836 884 Des_SetKey(&dec, key, desIv, DES_DECRYPTION);
ashleymills 0:714293de3836 885 Des_CbcDecrypt(&dec, input, input, length);
ashleymills 0:714293de3836 886 break;
ashleymills 0:714293de3836 887 }
ashleymills 0:714293de3836 888
ashleymills 0:714293de3836 889 case DES3_TYPE:
ashleymills 0:714293de3836 890 {
ashleymills 0:714293de3836 891 Des3 dec;
ashleymills 0:714293de3836 892 byte* desIv = key + 24;
ashleymills 0:714293de3836 893
ashleymills 0:714293de3836 894 if (version == PKCS5v2 || version == PKCS12)
ashleymills 0:714293de3836 895 desIv = cbcIv;
ashleymills 0:714293de3836 896 Des3_SetKey(&dec, key, desIv, DES_DECRYPTION);
ashleymills 0:714293de3836 897 Des3_CbcDecrypt(&dec, input, input, length);
ashleymills 0:714293de3836 898 break;
ashleymills 0:714293de3836 899 }
ashleymills 0:714293de3836 900 #endif
ashleymills 0:714293de3836 901 #ifndef NO_RC4
ashleymills 0:714293de3836 902 case RC4_TYPE:
ashleymills 0:714293de3836 903 {
ashleymills 0:714293de3836 904 Arc4 dec;
ashleymills 0:714293de3836 905
ashleymills 0:714293de3836 906 Arc4SetKey(&dec, key, derivedLen);
ashleymills 0:714293de3836 907 Arc4Process(&dec, input, input, length);
ashleymills 0:714293de3836 908 break;
ashleymills 0:714293de3836 909 }
ashleymills 0:714293de3836 910 #endif
ashleymills 0:714293de3836 911
ashleymills 0:714293de3836 912 default:
ashleymills 0:714293de3836 913 return ALGO_ID_E;
ashleymills 0:714293de3836 914 }
ashleymills 0:714293de3836 915
ashleymills 0:714293de3836 916 return 0;
ashleymills 0:714293de3836 917 }
ashleymills 0:714293de3836 918
ashleymills 0:714293de3836 919
ashleymills 0:714293de3836 920 /* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
ashleymills 0:714293de3836 921 of input */
ashleymills 0:714293de3836 922 int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
ashleymills 0:714293de3836 923 {
ashleymills 0:714293de3836 924 word32 inOutIdx = 0, oid;
ashleymills 0:714293de3836 925 int first, second, length, version, saltSz, id;
ashleymills 0:714293de3836 926 int iterations = 0;
ashleymills 0:714293de3836 927 byte salt[MAX_SALT_SIZE];
ashleymills 0:714293de3836 928 byte cbcIv[MAX_IV_SIZE];
ashleymills 0:714293de3836 929
ashleymills 0:714293de3836 930 if (GetSequence(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 931 return ASN_PARSE_E;
ashleymills 0:714293de3836 932
ashleymills 0:714293de3836 933 if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
ashleymills 0:714293de3836 934 return ASN_PARSE_E;
ashleymills 0:714293de3836 935
ashleymills 0:714293de3836 936 first = input[inOutIdx - 2]; /* PKCS version alwyas 2nd to last byte */
ashleymills 0:714293de3836 937 second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
ashleymills 0:714293de3836 938
ashleymills 0:714293de3836 939 if (CheckAlgo(first, second, &id, &version) < 0)
ashleymills 0:714293de3836 940 return ASN_INPUT_E; /* Algo ID error */
ashleymills 0:714293de3836 941
ashleymills 0:714293de3836 942 if (version == PKCS5v2) {
ashleymills 0:714293de3836 943
ashleymills 0:714293de3836 944 if (GetSequence(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 945 return ASN_PARSE_E;
ashleymills 0:714293de3836 946
ashleymills 0:714293de3836 947 if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
ashleymills 0:714293de3836 948 return ASN_PARSE_E;
ashleymills 0:714293de3836 949
ashleymills 0:714293de3836 950 if (oid != PBKDF2_OID)
ashleymills 0:714293de3836 951 return ASN_PARSE_E;
ashleymills 0:714293de3836 952 }
ashleymills 0:714293de3836 953
ashleymills 0:714293de3836 954 if (GetSequence(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 955 return ASN_PARSE_E;
ashleymills 0:714293de3836 956
ashleymills 0:714293de3836 957 if (input[inOutIdx++] != ASN_OCTET_STRING)
ashleymills 0:714293de3836 958 return ASN_PARSE_E;
ashleymills 0:714293de3836 959
ashleymills 0:714293de3836 960 if (GetLength(input, &inOutIdx, &saltSz, sz) < 0)
ashleymills 0:714293de3836 961 return ASN_PARSE_E;
ashleymills 0:714293de3836 962
ashleymills 0:714293de3836 963 if (saltSz > MAX_SALT_SIZE)
ashleymills 0:714293de3836 964 return ASN_PARSE_E;
ashleymills 0:714293de3836 965
ashleymills 0:714293de3836 966 XMEMCPY(salt, &input[inOutIdx], saltSz);
ashleymills 0:714293de3836 967 inOutIdx += saltSz;
ashleymills 0:714293de3836 968
ashleymills 0:714293de3836 969 if (GetShortInt(input, &inOutIdx, &iterations) < 0)
ashleymills 0:714293de3836 970 return ASN_PARSE_E;
ashleymills 0:714293de3836 971
ashleymills 0:714293de3836 972 if (version == PKCS5v2) {
ashleymills 0:714293de3836 973 /* get encryption algo */
ashleymills 0:714293de3836 974 if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
ashleymills 0:714293de3836 975 return ASN_PARSE_E;
ashleymills 0:714293de3836 976
ashleymills 0:714293de3836 977 if (CheckAlgoV2(oid, &id) < 0)
ashleymills 0:714293de3836 978 return ASN_PARSE_E; /* PKCS v2 algo id error */
ashleymills 0:714293de3836 979
ashleymills 0:714293de3836 980 if (input[inOutIdx++] != ASN_OCTET_STRING)
ashleymills 0:714293de3836 981 return ASN_PARSE_E;
ashleymills 0:714293de3836 982
ashleymills 0:714293de3836 983 if (GetLength(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 984 return ASN_PARSE_E;
ashleymills 0:714293de3836 985
ashleymills 0:714293de3836 986 XMEMCPY(cbcIv, &input[inOutIdx], length);
ashleymills 0:714293de3836 987 inOutIdx += length;
ashleymills 0:714293de3836 988 }
ashleymills 0:714293de3836 989
ashleymills 0:714293de3836 990 if (input[inOutIdx++] != ASN_OCTET_STRING)
ashleymills 0:714293de3836 991 return ASN_PARSE_E;
ashleymills 0:714293de3836 992
ashleymills 0:714293de3836 993 if (GetLength(input, &inOutIdx, &length, sz) < 0)
ashleymills 0:714293de3836 994 return ASN_PARSE_E;
ashleymills 0:714293de3836 995
ashleymills 0:714293de3836 996 if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id,
ashleymills 0:714293de3836 997 input + inOutIdx, length, version, cbcIv) < 0)
ashleymills 0:714293de3836 998 return ASN_INPUT_E; /* decrypt failure */
ashleymills 0:714293de3836 999
ashleymills 0:714293de3836 1000 XMEMMOVE(input, input + inOutIdx, length);
ashleymills 0:714293de3836 1001 return ToTraditional(input, length);
ashleymills 0:714293de3836 1002 }
ashleymills 0:714293de3836 1003
ashleymills 0:714293de3836 1004 #endif /* NO_PWDBASED */
ashleymills 0:714293de3836 1005
ashleymills 0:714293de3836 1006 #ifndef NO_RSA
ashleymills 0:714293de3836 1007
ashleymills 0:714293de3836 1008 int RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
ashleymills 0:714293de3836 1009 word32 inSz)
ashleymills 0:714293de3836 1010 {
ashleymills 0:714293de3836 1011 int length;
ashleymills 0:714293de3836 1012
ashleymills 0:714293de3836 1013 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1014 return ASN_PARSE_E;
ashleymills 0:714293de3836 1015
ashleymills 0:714293de3836 1016 key->type = RSA_PUBLIC;
ashleymills 0:714293de3836 1017
ashleymills 0:714293de3836 1018 #ifdef OPENSSL_EXTRA
ashleymills 0:714293de3836 1019 {
ashleymills 0:714293de3836 1020 byte b = input[*inOutIdx];
ashleymills 0:714293de3836 1021 if (b != ASN_INTEGER) {
ashleymills 0:714293de3836 1022 /* not from decoded cert, will have algo id, skip past */
ashleymills 0:714293de3836 1023 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1024 return ASN_PARSE_E;
ashleymills 0:714293de3836 1025
ashleymills 0:714293de3836 1026 b = input[(*inOutIdx)++];
ashleymills 0:714293de3836 1027 if (b != ASN_OBJECT_ID)
ashleymills 0:714293de3836 1028 return ASN_OBJECT_ID_E;
ashleymills 0:714293de3836 1029
ashleymills 0:714293de3836 1030 if (GetLength(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1031 return ASN_PARSE_E;
ashleymills 0:714293de3836 1032
ashleymills 0:714293de3836 1033 *inOutIdx += length; /* skip past */
ashleymills 0:714293de3836 1034
ashleymills 0:714293de3836 1035 /* could have NULL tag and 0 terminator, but may not */
ashleymills 0:714293de3836 1036 b = input[(*inOutIdx)++];
ashleymills 0:714293de3836 1037
ashleymills 0:714293de3836 1038 if (b == ASN_TAG_NULL) {
ashleymills 0:714293de3836 1039 b = input[(*inOutIdx)++];
ashleymills 0:714293de3836 1040 if (b != 0)
ashleymills 0:714293de3836 1041 return ASN_EXPECT_0_E;
ashleymills 0:714293de3836 1042 }
ashleymills 0:714293de3836 1043 else
ashleymills 0:714293de3836 1044 /* go back, didn't have it */
ashleymills 0:714293de3836 1045 (*inOutIdx)--;
ashleymills 0:714293de3836 1046
ashleymills 0:714293de3836 1047 /* should have bit tag length and seq next */
ashleymills 0:714293de3836 1048 b = input[(*inOutIdx)++];
ashleymills 0:714293de3836 1049 if (b != ASN_BIT_STRING)
ashleymills 0:714293de3836 1050 return ASN_BITSTR_E;
ashleymills 0:714293de3836 1051
ashleymills 0:714293de3836 1052 if (GetLength(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1053 return ASN_PARSE_E;
ashleymills 0:714293de3836 1054
ashleymills 0:714293de3836 1055 /* could have 0 */
ashleymills 0:714293de3836 1056 b = input[(*inOutIdx)++];
ashleymills 0:714293de3836 1057 if (b != 0)
ashleymills 0:714293de3836 1058 (*inOutIdx)--;
ashleymills 0:714293de3836 1059
ashleymills 0:714293de3836 1060 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1061 return ASN_PARSE_E;
ashleymills 0:714293de3836 1062 } /* end if */
ashleymills 0:714293de3836 1063 } /* openssl var block */
ashleymills 0:714293de3836 1064 #endif /* OPENSSL_EXTRA */
ashleymills 0:714293de3836 1065
ashleymills 0:714293de3836 1066 if (GetInt(&key->n, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1067 GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
ashleymills 0:714293de3836 1068
ashleymills 0:714293de3836 1069 return 0;
ashleymills 0:714293de3836 1070 }
ashleymills 0:714293de3836 1071
ashleymills 0:714293de3836 1072 #endif
ashleymills 0:714293de3836 1073
ashleymills 0:714293de3836 1074 #ifndef NO_DH
ashleymills 0:714293de3836 1075
ashleymills 0:714293de3836 1076 int DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
ashleymills 0:714293de3836 1077 {
ashleymills 0:714293de3836 1078 int length;
ashleymills 0:714293de3836 1079
ashleymills 0:714293de3836 1080 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1081 return ASN_PARSE_E;
ashleymills 0:714293de3836 1082
ashleymills 0:714293de3836 1083 if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1084 GetInt(&key->g, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
ashleymills 0:714293de3836 1085
ashleymills 0:714293de3836 1086 return 0;
ashleymills 0:714293de3836 1087 }
ashleymills 0:714293de3836 1088
ashleymills 0:714293de3836 1089 int DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz)
ashleymills 0:714293de3836 1090 {
ashleymills 0:714293de3836 1091 /* may have leading 0 */
ashleymills 0:714293de3836 1092 if (p[0] == 0) {
ashleymills 0:714293de3836 1093 pSz--; p++;
ashleymills 0:714293de3836 1094 }
ashleymills 0:714293de3836 1095
ashleymills 0:714293de3836 1096 if (g[0] == 0) {
ashleymills 0:714293de3836 1097 gSz--; g++;
ashleymills 0:714293de3836 1098 }
ashleymills 0:714293de3836 1099
ashleymills 0:714293de3836 1100 if (mp_init(&key->p) != MP_OKAY)
ashleymills 0:714293de3836 1101 return MP_INIT_E;
ashleymills 0:714293de3836 1102 if (mp_read_unsigned_bin(&key->p, p, pSz) != 0) {
ashleymills 0:714293de3836 1103 mp_clear(&key->p);
ashleymills 0:714293de3836 1104 return ASN_DH_KEY_E;
ashleymills 0:714293de3836 1105 }
ashleymills 0:714293de3836 1106
ashleymills 0:714293de3836 1107 if (mp_init(&key->g) != MP_OKAY) {
ashleymills 0:714293de3836 1108 mp_clear(&key->p);
ashleymills 0:714293de3836 1109 return MP_INIT_E;
ashleymills 0:714293de3836 1110 }
ashleymills 0:714293de3836 1111 if (mp_read_unsigned_bin(&key->g, g, gSz) != 0) {
ashleymills 0:714293de3836 1112 mp_clear(&key->g);
ashleymills 0:714293de3836 1113 mp_clear(&key->p);
ashleymills 0:714293de3836 1114 return ASN_DH_KEY_E;
ashleymills 0:714293de3836 1115 }
ashleymills 0:714293de3836 1116
ashleymills 0:714293de3836 1117 return 0;
ashleymills 0:714293de3836 1118 }
ashleymills 0:714293de3836 1119
ashleymills 0:714293de3836 1120
ashleymills 0:714293de3836 1121 #ifdef OPENSSL_EXTRA
ashleymills 0:714293de3836 1122
ashleymills 0:714293de3836 1123 int DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
ashleymills 0:714293de3836 1124 byte* g, word32* gInOutSz)
ashleymills 0:714293de3836 1125 {
ashleymills 0:714293de3836 1126 word32 i = 0;
ashleymills 0:714293de3836 1127 byte b;
ashleymills 0:714293de3836 1128 int length;
ashleymills 0:714293de3836 1129
ashleymills 0:714293de3836 1130 if (GetSequence(input, &i, &length, inSz) < 0)
ashleymills 0:714293de3836 1131 return ASN_PARSE_E;
ashleymills 0:714293de3836 1132
ashleymills 0:714293de3836 1133 b = input[i++];
ashleymills 0:714293de3836 1134 if (b != ASN_INTEGER)
ashleymills 0:714293de3836 1135 return ASN_PARSE_E;
ashleymills 0:714293de3836 1136
ashleymills 0:714293de3836 1137 if (GetLength(input, &i, &length, inSz) < 0)
ashleymills 0:714293de3836 1138 return ASN_PARSE_E;
ashleymills 0:714293de3836 1139
ashleymills 0:714293de3836 1140 if ( (b = input[i++]) == 0x00)
ashleymills 0:714293de3836 1141 length--;
ashleymills 0:714293de3836 1142 else
ashleymills 0:714293de3836 1143 i--;
ashleymills 0:714293de3836 1144
ashleymills 0:714293de3836 1145 if (length <= (int)*pInOutSz) {
ashleymills 0:714293de3836 1146 XMEMCPY(p, &input[i], length);
ashleymills 0:714293de3836 1147 *pInOutSz = length;
ashleymills 0:714293de3836 1148 }
ashleymills 0:714293de3836 1149 else
ashleymills 0:714293de3836 1150 return BUFFER_E;
ashleymills 0:714293de3836 1151
ashleymills 0:714293de3836 1152 i += length;
ashleymills 0:714293de3836 1153
ashleymills 0:714293de3836 1154 b = input[i++];
ashleymills 0:714293de3836 1155 if (b != ASN_INTEGER)
ashleymills 0:714293de3836 1156 return ASN_PARSE_E;
ashleymills 0:714293de3836 1157
ashleymills 0:714293de3836 1158 if (GetLength(input, &i, &length, inSz) < 0)
ashleymills 0:714293de3836 1159 return ASN_PARSE_E;
ashleymills 0:714293de3836 1160
ashleymills 0:714293de3836 1161 if (length <= (int)*gInOutSz) {
ashleymills 0:714293de3836 1162 XMEMCPY(g, &input[i], length);
ashleymills 0:714293de3836 1163 *gInOutSz = length;
ashleymills 0:714293de3836 1164 }
ashleymills 0:714293de3836 1165 else
ashleymills 0:714293de3836 1166 return BUFFER_E;
ashleymills 0:714293de3836 1167
ashleymills 0:714293de3836 1168 return 0;
ashleymills 0:714293de3836 1169 }
ashleymills 0:714293de3836 1170
ashleymills 0:714293de3836 1171 #endif /* OPENSSL_EXTRA */
ashleymills 0:714293de3836 1172 #endif /* NO_DH */
ashleymills 0:714293de3836 1173
ashleymills 0:714293de3836 1174
ashleymills 0:714293de3836 1175 #ifndef NO_DSA
ashleymills 0:714293de3836 1176
ashleymills 0:714293de3836 1177 int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
ashleymills 0:714293de3836 1178 word32 inSz)
ashleymills 0:714293de3836 1179 {
ashleymills 0:714293de3836 1180 int length;
ashleymills 0:714293de3836 1181
ashleymills 0:714293de3836 1182 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1183 return ASN_PARSE_E;
ashleymills 0:714293de3836 1184
ashleymills 0:714293de3836 1185 if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1186 GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1187 GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1188 GetInt(&key->y, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
ashleymills 0:714293de3836 1189
ashleymills 0:714293de3836 1190 key->type = DSA_PUBLIC;
ashleymills 0:714293de3836 1191 return 0;
ashleymills 0:714293de3836 1192 }
ashleymills 0:714293de3836 1193
ashleymills 0:714293de3836 1194
ashleymills 0:714293de3836 1195 int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
ashleymills 0:714293de3836 1196 word32 inSz)
ashleymills 0:714293de3836 1197 {
ashleymills 0:714293de3836 1198 int length, version;
ashleymills 0:714293de3836 1199
ashleymills 0:714293de3836 1200 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 1201 return ASN_PARSE_E;
ashleymills 0:714293de3836 1202
ashleymills 0:714293de3836 1203 if (GetMyVersion(input, inOutIdx, &version) < 0)
ashleymills 0:714293de3836 1204 return ASN_PARSE_E;
ashleymills 0:714293de3836 1205
ashleymills 0:714293de3836 1206 if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1207 GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1208 GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1209 GetInt(&key->y, input, inOutIdx, inSz) < 0 ||
ashleymills 0:714293de3836 1210 GetInt(&key->x, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
ashleymills 0:714293de3836 1211
ashleymills 0:714293de3836 1212 key->type = DSA_PRIVATE;
ashleymills 0:714293de3836 1213 return 0;
ashleymills 0:714293de3836 1214 }
ashleymills 0:714293de3836 1215
ashleymills 0:714293de3836 1216 #endif /* NO_DSA */
ashleymills 0:714293de3836 1217
ashleymills 0:714293de3836 1218
ashleymills 0:714293de3836 1219 void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
ashleymills 0:714293de3836 1220 {
ashleymills 0:714293de3836 1221 cert->publicKey = 0;
ashleymills 0:714293de3836 1222 cert->pubKeyStored = 0;
ashleymills 0:714293de3836 1223 cert->signature = 0;
ashleymills 0:714293de3836 1224 cert->subjectCN = 0;
ashleymills 0:714293de3836 1225 cert->subjectCNLen = 0;
ashleymills 0:714293de3836 1226 cert->subjectCNStored = 0;
ashleymills 0:714293de3836 1227 cert->altNames = NULL;
ashleymills 0:714293de3836 1228 cert->issuer[0] = '\0';
ashleymills 0:714293de3836 1229 cert->subject[0] = '\0';
ashleymills 0:714293de3836 1230 cert->source = source; /* don't own */
ashleymills 0:714293de3836 1231 cert->srcIdx = 0;
ashleymills 0:714293de3836 1232 cert->maxIdx = inSz; /* can't go over this index */
ashleymills 0:714293de3836 1233 cert->heap = heap;
ashleymills 0:714293de3836 1234 XMEMSET(cert->serial, 0, EXTERNAL_SERIAL_SIZE);
ashleymills 0:714293de3836 1235 cert->serialSz = 0;
ashleymills 0:714293de3836 1236 cert->extensions = 0;
ashleymills 0:714293de3836 1237 cert->extensionsSz = 0;
ashleymills 0:714293de3836 1238 cert->extensionsIdx = 0;
ashleymills 0:714293de3836 1239 cert->extAuthInfo = NULL;
ashleymills 0:714293de3836 1240 cert->extAuthInfoSz = 0;
ashleymills 0:714293de3836 1241 cert->extCrlInfo = NULL;
ashleymills 0:714293de3836 1242 cert->extCrlInfoSz = 0;
ashleymills 0:714293de3836 1243 XMEMSET(cert->extSubjKeyId, 0, SHA_SIZE);
ashleymills 0:714293de3836 1244 cert->extSubjKeyIdSet = 0;
ashleymills 0:714293de3836 1245 XMEMSET(cert->extAuthKeyId, 0, SHA_SIZE);
ashleymills 0:714293de3836 1246 cert->extAuthKeyIdSet = 0;
ashleymills 0:714293de3836 1247 cert->isCA = 0;
ashleymills 0:714293de3836 1248 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1249 cert->subjectSN = 0;
ashleymills 0:714293de3836 1250 cert->subjectSNLen = 0;
ashleymills 0:714293de3836 1251 cert->subjectC = 0;
ashleymills 0:714293de3836 1252 cert->subjectCLen = 0;
ashleymills 0:714293de3836 1253 cert->subjectL = 0;
ashleymills 0:714293de3836 1254 cert->subjectLLen = 0;
ashleymills 0:714293de3836 1255 cert->subjectST = 0;
ashleymills 0:714293de3836 1256 cert->subjectSTLen = 0;
ashleymills 0:714293de3836 1257 cert->subjectO = 0;
ashleymills 0:714293de3836 1258 cert->subjectOLen = 0;
ashleymills 0:714293de3836 1259 cert->subjectOU = 0;
ashleymills 0:714293de3836 1260 cert->subjectOULen = 0;
ashleymills 0:714293de3836 1261 cert->subjectEmail = 0;
ashleymills 0:714293de3836 1262 cert->subjectEmailLen = 0;
ashleymills 0:714293de3836 1263 cert->beforeDate = 0;
ashleymills 0:714293de3836 1264 cert->beforeDateLen = 0;
ashleymills 0:714293de3836 1265 cert->afterDate = 0;
ashleymills 0:714293de3836 1266 cert->afterDateLen = 0;
ashleymills 0:714293de3836 1267 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1268 }
ashleymills 0:714293de3836 1269
ashleymills 0:714293de3836 1270
ashleymills 0:714293de3836 1271 void FreeAltNames(DNS_entry* altNames, void* heap)
ashleymills 0:714293de3836 1272 {
ashleymills 0:714293de3836 1273 (void)heap;
ashleymills 0:714293de3836 1274
ashleymills 0:714293de3836 1275 while (altNames) {
ashleymills 0:714293de3836 1276 DNS_entry* tmp = altNames->next;
ashleymills 0:714293de3836 1277
ashleymills 0:714293de3836 1278 XFREE(altNames->name, heap, DYNAMIC_TYPE_ALTNAME);
ashleymills 0:714293de3836 1279 XFREE(altNames, heap, DYNAMIC_TYPE_ALTNAME);
ashleymills 0:714293de3836 1280 altNames = tmp;
ashleymills 0:714293de3836 1281 }
ashleymills 0:714293de3836 1282 }
ashleymills 0:714293de3836 1283
ashleymills 0:714293de3836 1284
ashleymills 0:714293de3836 1285 void FreeDecodedCert(DecodedCert* cert)
ashleymills 0:714293de3836 1286 {
ashleymills 0:714293de3836 1287 if (cert->subjectCNStored == 1)
ashleymills 0:714293de3836 1288 XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
ashleymills 0:714293de3836 1289 if (cert->pubKeyStored == 1)
ashleymills 0:714293de3836 1290 XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
ashleymills 0:714293de3836 1291 if (cert->altNames)
ashleymills 0:714293de3836 1292 FreeAltNames(cert->altNames, cert->heap);
ashleymills 0:714293de3836 1293 }
ashleymills 0:714293de3836 1294
ashleymills 0:714293de3836 1295
ashleymills 0:714293de3836 1296 static int GetCertHeader(DecodedCert* cert)
ashleymills 0:714293de3836 1297 {
ashleymills 0:714293de3836 1298 int ret = 0, version, len;
ashleymills 0:714293de3836 1299 byte serialTmp[EXTERNAL_SERIAL_SIZE];
ashleymills 0:714293de3836 1300 mp_int mpi;
ashleymills 0:714293de3836 1301
ashleymills 0:714293de3836 1302 if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1303 return ASN_PARSE_E;
ashleymills 0:714293de3836 1304
ashleymills 0:714293de3836 1305 cert->certBegin = cert->srcIdx;
ashleymills 0:714293de3836 1306
ashleymills 0:714293de3836 1307 if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1308 return ASN_PARSE_E;
ashleymills 0:714293de3836 1309 cert->sigIndex = len + cert->srcIdx;
ashleymills 0:714293de3836 1310
ashleymills 0:714293de3836 1311 if (GetExplicitVersion(cert->source, &cert->srcIdx, &version) < 0)
ashleymills 0:714293de3836 1312 return ASN_PARSE_E;
ashleymills 0:714293de3836 1313
ashleymills 0:714293de3836 1314 if (GetInt(&mpi, cert->source, &cert->srcIdx, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1315 return ASN_PARSE_E;
ashleymills 0:714293de3836 1316
ashleymills 0:714293de3836 1317 len = mp_unsigned_bin_size(&mpi);
ashleymills 0:714293de3836 1318 if (len < (int)sizeof(serialTmp)) {
ashleymills 0:714293de3836 1319 if (mp_to_unsigned_bin(&mpi, serialTmp) == MP_OKAY) {
ashleymills 0:714293de3836 1320 if (len > EXTERNAL_SERIAL_SIZE)
ashleymills 0:714293de3836 1321 len = EXTERNAL_SERIAL_SIZE;
ashleymills 0:714293de3836 1322 XMEMCPY(cert->serial, serialTmp, len);
ashleymills 0:714293de3836 1323 cert->serialSz = len;
ashleymills 0:714293de3836 1324 }
ashleymills 0:714293de3836 1325 }
ashleymills 0:714293de3836 1326 mp_clear(&mpi);
ashleymills 0:714293de3836 1327 return ret;
ashleymills 0:714293de3836 1328 }
ashleymills 0:714293de3836 1329
ashleymills 0:714293de3836 1330 #if !defined(NO_RSA)
ashleymills 0:714293de3836 1331 /* Store Rsa Key, may save later, Dsa could use in future */
ashleymills 0:714293de3836 1332 static int StoreRsaKey(DecodedCert* cert)
ashleymills 0:714293de3836 1333 {
ashleymills 0:714293de3836 1334 int length;
ashleymills 0:714293de3836 1335 word32 read = cert->srcIdx;
ashleymills 0:714293de3836 1336
ashleymills 0:714293de3836 1337 if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1338 return ASN_PARSE_E;
ashleymills 0:714293de3836 1339
ashleymills 0:714293de3836 1340 read = cert->srcIdx - read;
ashleymills 0:714293de3836 1341 length += read;
ashleymills 0:714293de3836 1342
ashleymills 0:714293de3836 1343 while (read--)
ashleymills 0:714293de3836 1344 cert->srcIdx--;
ashleymills 0:714293de3836 1345
ashleymills 0:714293de3836 1346 cert->pubKeySize = length;
ashleymills 0:714293de3836 1347 cert->publicKey = cert->source + cert->srcIdx;
ashleymills 0:714293de3836 1348 cert->srcIdx += length;
ashleymills 0:714293de3836 1349
ashleymills 0:714293de3836 1350 return 0;
ashleymills 0:714293de3836 1351 }
ashleymills 0:714293de3836 1352 #endif
ashleymills 0:714293de3836 1353
ashleymills 0:714293de3836 1354
ashleymills 0:714293de3836 1355 #ifdef HAVE_ECC
ashleymills 0:714293de3836 1356
ashleymills 0:714293de3836 1357 /* return 0 on sucess if the ECC curve oid sum is supported */
ashleymills 0:714293de3836 1358 static int CheckCurve(word32 oid)
ashleymills 0:714293de3836 1359 {
ashleymills 0:714293de3836 1360 if (oid != ECC_256R1 && oid != ECC_384R1 && oid != ECC_521R1 && oid !=
ashleymills 0:714293de3836 1361 ECC_160R1 && oid != ECC_192R1 && oid != ECC_224R1)
ashleymills 0:714293de3836 1362 return ALGO_ID_E;
ashleymills 0:714293de3836 1363
ashleymills 0:714293de3836 1364 return 0;
ashleymills 0:714293de3836 1365 }
ashleymills 0:714293de3836 1366
ashleymills 0:714293de3836 1367 #endif /* HAVE_ECC */
ashleymills 0:714293de3836 1368
ashleymills 0:714293de3836 1369
ashleymills 0:714293de3836 1370 static int GetKey(DecodedCert* cert)
ashleymills 0:714293de3836 1371 {
ashleymills 0:714293de3836 1372 int length;
ashleymills 0:714293de3836 1373 #ifdef HAVE_NTRU
ashleymills 0:714293de3836 1374 int tmpIdx = cert->srcIdx;
ashleymills 0:714293de3836 1375 #endif
ashleymills 0:714293de3836 1376
ashleymills 0:714293de3836 1377 if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1378 return ASN_PARSE_E;
ashleymills 0:714293de3836 1379
ashleymills 0:714293de3836 1380 if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1381 return ASN_PARSE_E;
ashleymills 0:714293de3836 1382
ashleymills 0:714293de3836 1383 switch (cert->keyOID) {
ashleymills 0:714293de3836 1384 case DSAk:
ashleymills 0:714293de3836 1385 /* do nothing */
ashleymills 0:714293de3836 1386 break;
ashleymills 0:714293de3836 1387 #ifndef NO_RSA
ashleymills 0:714293de3836 1388 case RSAk:
ashleymills 0:714293de3836 1389 {
ashleymills 0:714293de3836 1390 byte b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1391 if (b != ASN_BIT_STRING)
ashleymills 0:714293de3836 1392 return ASN_BITSTR_E;
ashleymills 0:714293de3836 1393
ashleymills 0:714293de3836 1394 if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
ashleymills 0:714293de3836 1395 return ASN_PARSE_E;
ashleymills 0:714293de3836 1396 b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1397 if (b != 0x00)
ashleymills 0:714293de3836 1398 return ASN_EXPECT_0_E;
ashleymills 0:714293de3836 1399
ashleymills 0:714293de3836 1400 return StoreRsaKey(cert);
ashleymills 0:714293de3836 1401 }
ashleymills 0:714293de3836 1402
ashleymills 0:714293de3836 1403 #endif /* NO_RSA */
ashleymills 0:714293de3836 1404 #ifdef HAVE_NTRU
ashleymills 0:714293de3836 1405 case NTRUk:
ashleymills 0:714293de3836 1406 {
ashleymills 0:714293de3836 1407 const byte* key = &cert->source[tmpIdx];
ashleymills 0:714293de3836 1408 byte* next = (byte*)key;
ashleymills 0:714293de3836 1409 word16 keyLen;
ashleymills 0:714293de3836 1410 byte keyBlob[MAX_NTRU_KEY_SZ];
ashleymills 0:714293de3836 1411
ashleymills 0:714293de3836 1412 word32 rc = crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
ashleymills 0:714293de3836 1413 &keyLen, NULL, &next);
ashleymills 0:714293de3836 1414
ashleymills 0:714293de3836 1415 if (rc != NTRU_OK)
ashleymills 0:714293de3836 1416 return ASN_NTRU_KEY_E;
ashleymills 0:714293de3836 1417 if (keyLen > sizeof(keyBlob))
ashleymills 0:714293de3836 1418 return ASN_NTRU_KEY_E;
ashleymills 0:714293de3836 1419
ashleymills 0:714293de3836 1420 rc = crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,&keyLen,
ashleymills 0:714293de3836 1421 keyBlob, &next);
ashleymills 0:714293de3836 1422 if (rc != NTRU_OK)
ashleymills 0:714293de3836 1423 return ASN_NTRU_KEY_E;
ashleymills 0:714293de3836 1424
ashleymills 0:714293de3836 1425 if ( (next - key) < 0)
ashleymills 0:714293de3836 1426 return ASN_NTRU_KEY_E;
ashleymills 0:714293de3836 1427
ashleymills 0:714293de3836 1428 cert->srcIdx = tmpIdx + (int)(next - key);
ashleymills 0:714293de3836 1429
ashleymills 0:714293de3836 1430 cert->publicKey = (byte*) XMALLOC(keyLen, cert->heap,
ashleymills 0:714293de3836 1431 DYNAMIC_TYPE_PUBLIC_KEY);
ashleymills 0:714293de3836 1432 if (cert->publicKey == NULL)
ashleymills 0:714293de3836 1433 return MEMORY_E;
ashleymills 0:714293de3836 1434 XMEMCPY(cert->publicKey, keyBlob, keyLen);
ashleymills 0:714293de3836 1435 cert->pubKeyStored = 1;
ashleymills 0:714293de3836 1436 cert->pubKeySize = keyLen;
ashleymills 0:714293de3836 1437 }
ashleymills 0:714293de3836 1438 break;
ashleymills 0:714293de3836 1439 #endif /* HAVE_NTRU */
ashleymills 0:714293de3836 1440 #ifdef HAVE_ECC
ashleymills 0:714293de3836 1441 case ECDSAk:
ashleymills 0:714293de3836 1442 {
ashleymills 0:714293de3836 1443 word32 oid = 0;
ashleymills 0:714293de3836 1444 int oidSz = 0;
ashleymills 0:714293de3836 1445 byte b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1446
ashleymills 0:714293de3836 1447 if (b != ASN_OBJECT_ID)
ashleymills 0:714293de3836 1448 return ASN_OBJECT_ID_E;
ashleymills 0:714293de3836 1449
ashleymills 0:714293de3836 1450 if (GetLength(cert->source,&cert->srcIdx,&oidSz,cert->maxIdx) < 0)
ashleymills 0:714293de3836 1451 return ASN_PARSE_E;
ashleymills 0:714293de3836 1452
ashleymills 0:714293de3836 1453 while(oidSz--)
ashleymills 0:714293de3836 1454 oid += cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1455 if (CheckCurve(oid) < 0)
ashleymills 0:714293de3836 1456 return ECC_CURVE_OID_E;
ashleymills 0:714293de3836 1457
ashleymills 0:714293de3836 1458 /* key header */
ashleymills 0:714293de3836 1459 b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1460 if (b != ASN_BIT_STRING)
ashleymills 0:714293de3836 1461 return ASN_BITSTR_E;
ashleymills 0:714293de3836 1462
ashleymills 0:714293de3836 1463 if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
ashleymills 0:714293de3836 1464 return ASN_PARSE_E;
ashleymills 0:714293de3836 1465 b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1466 if (b != 0x00)
ashleymills 0:714293de3836 1467 return ASN_EXPECT_0_E;
ashleymills 0:714293de3836 1468
ashleymills 0:714293de3836 1469 /* actual key, use length - 1 since ate preceding 0 */
ashleymills 0:714293de3836 1470 length -= 1;
ashleymills 0:714293de3836 1471
ashleymills 0:714293de3836 1472 cert->publicKey = (byte*) XMALLOC(length, cert->heap,
ashleymills 0:714293de3836 1473 DYNAMIC_TYPE_PUBLIC_KEY);
ashleymills 0:714293de3836 1474 if (cert->publicKey == NULL)
ashleymills 0:714293de3836 1475 return MEMORY_E;
ashleymills 0:714293de3836 1476 XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length);
ashleymills 0:714293de3836 1477 cert->pubKeyStored = 1;
ashleymills 0:714293de3836 1478 cert->pubKeySize = length;
ashleymills 0:714293de3836 1479
ashleymills 0:714293de3836 1480 cert->srcIdx += length;
ashleymills 0:714293de3836 1481 }
ashleymills 0:714293de3836 1482 break;
ashleymills 0:714293de3836 1483 #endif /* HAVE_ECC */
ashleymills 0:714293de3836 1484 default:
ashleymills 0:714293de3836 1485 return ASN_UNKNOWN_OID_E;
ashleymills 0:714293de3836 1486 }
ashleymills 0:714293de3836 1487
ashleymills 0:714293de3836 1488 return 0;
ashleymills 0:714293de3836 1489 }
ashleymills 0:714293de3836 1490
ashleymills 0:714293de3836 1491
ashleymills 0:714293de3836 1492 /* process NAME, either issuer or subject */
ashleymills 0:714293de3836 1493 static int GetName(DecodedCert* cert, int nameType)
ashleymills 0:714293de3836 1494 {
ashleymills 0:714293de3836 1495 Sha sha; /* MUST have SHA-1 hash for cert names */
ashleymills 0:714293de3836 1496 int length; /* length of all distinguished names */
ashleymills 0:714293de3836 1497 int dummy;
ashleymills 0:714293de3836 1498 char* full = (nameType == ISSUER) ? cert->issuer : cert->subject;
ashleymills 0:714293de3836 1499 word32 idx;
ashleymills 0:714293de3836 1500
ashleymills 0:714293de3836 1501 CYASSL_MSG("Getting Cert Name");
ashleymills 0:714293de3836 1502
ashleymills 0:714293de3836 1503 if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) {
ashleymills 0:714293de3836 1504 CYASSL_MSG("Trying optional prefix...");
ashleymills 0:714293de3836 1505
ashleymills 0:714293de3836 1506 if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1507 return ASN_PARSE_E;
ashleymills 0:714293de3836 1508
ashleymills 0:714293de3836 1509 cert->srcIdx += length;
ashleymills 0:714293de3836 1510 CYASSL_MSG("Got optional prefix");
ashleymills 0:714293de3836 1511 }
ashleymills 0:714293de3836 1512
ashleymills 0:714293de3836 1513 /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
ashleymills 0:714293de3836 1514 * calculated over the entire DER encoding of the Name field, including
ashleymills 0:714293de3836 1515 * the tag and length. */
ashleymills 0:714293de3836 1516 idx = cert->srcIdx;
ashleymills 0:714293de3836 1517 if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1518 return ASN_PARSE_E;
ashleymills 0:714293de3836 1519
ashleymills 0:714293de3836 1520 InitSha(&sha);
ashleymills 0:714293de3836 1521 ShaUpdate(&sha, &cert->source[idx], length + cert->srcIdx - idx);
ashleymills 0:714293de3836 1522 if (nameType == ISSUER)
ashleymills 0:714293de3836 1523 ShaFinal(&sha, cert->issuerHash);
ashleymills 0:714293de3836 1524 else
ashleymills 0:714293de3836 1525 ShaFinal(&sha, cert->subjectHash);
ashleymills 0:714293de3836 1526
ashleymills 0:714293de3836 1527 length += cert->srcIdx;
ashleymills 0:714293de3836 1528 idx = 0;
ashleymills 0:714293de3836 1529
ashleymills 0:714293de3836 1530 while (cert->srcIdx < (word32)length) {
ashleymills 0:714293de3836 1531 byte b;
ashleymills 0:714293de3836 1532 byte joint[2];
ashleymills 0:714293de3836 1533 byte tooBig = FALSE;
ashleymills 0:714293de3836 1534 int oidSz;
ashleymills 0:714293de3836 1535
ashleymills 0:714293de3836 1536 if (GetSet(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) {
ashleymills 0:714293de3836 1537 CYASSL_MSG("Cert name lacks set header, trying sequence");
ashleymills 0:714293de3836 1538 }
ashleymills 0:714293de3836 1539
ashleymills 0:714293de3836 1540 if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1541 return ASN_PARSE_E;
ashleymills 0:714293de3836 1542
ashleymills 0:714293de3836 1543 b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1544 if (b != ASN_OBJECT_ID)
ashleymills 0:714293de3836 1545 return ASN_OBJECT_ID_E;
ashleymills 0:714293de3836 1546
ashleymills 0:714293de3836 1547 if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1548 return ASN_PARSE_E;
ashleymills 0:714293de3836 1549
ashleymills 0:714293de3836 1550 XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
ashleymills 0:714293de3836 1551
ashleymills 0:714293de3836 1552 /* v1 name types */
ashleymills 0:714293de3836 1553 if (joint[0] == 0x55 && joint[1] == 0x04) {
ashleymills 0:714293de3836 1554 byte id;
ashleymills 0:714293de3836 1555 byte copy = FALSE;
ashleymills 0:714293de3836 1556 int strLen;
ashleymills 0:714293de3836 1557
ashleymills 0:714293de3836 1558 cert->srcIdx += 2;
ashleymills 0:714293de3836 1559 id = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1560 b = cert->source[cert->srcIdx++]; /* strType */
ashleymills 0:714293de3836 1561 (void)b; /* may want to validate? */
ashleymills 0:714293de3836 1562
ashleymills 0:714293de3836 1563 if (GetLength(cert->source, &cert->srcIdx, &strLen,
ashleymills 0:714293de3836 1564 cert->maxIdx) < 0)
ashleymills 0:714293de3836 1565 return ASN_PARSE_E;
ashleymills 0:714293de3836 1566
ashleymills 0:714293de3836 1567 if ( (strLen + 4) > (int)(ASN_NAME_MAX - idx)) {
ashleymills 0:714293de3836 1568 /* include biggest pre fix header too 4 = "/CN=" */
ashleymills 0:714293de3836 1569 CYASSL_MSG("ASN Name too big, skipping");
ashleymills 0:714293de3836 1570 tooBig = TRUE;
ashleymills 0:714293de3836 1571 }
ashleymills 0:714293de3836 1572
ashleymills 0:714293de3836 1573 if (id == ASN_COMMON_NAME) {
ashleymills 0:714293de3836 1574 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1575 cert->subjectCN = (char *)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1576 cert->subjectCNLen = strLen;
ashleymills 0:714293de3836 1577 }
ashleymills 0:714293de3836 1578
ashleymills 0:714293de3836 1579 if (!tooBig) {
ashleymills 0:714293de3836 1580 XMEMCPY(&full[idx], "/CN=", 4);
ashleymills 0:714293de3836 1581 idx += 4;
ashleymills 0:714293de3836 1582 copy = TRUE;
ashleymills 0:714293de3836 1583 }
ashleymills 0:714293de3836 1584 }
ashleymills 0:714293de3836 1585 else if (id == ASN_SUR_NAME) {
ashleymills 0:714293de3836 1586 if (!tooBig) {
ashleymills 0:714293de3836 1587 XMEMCPY(&full[idx], "/SN=", 4);
ashleymills 0:714293de3836 1588 idx += 4;
ashleymills 0:714293de3836 1589 copy = TRUE;
ashleymills 0:714293de3836 1590 }
ashleymills 0:714293de3836 1591 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1592 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1593 cert->subjectSN = (char*)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1594 cert->subjectSNLen = strLen;
ashleymills 0:714293de3836 1595 }
ashleymills 0:714293de3836 1596 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1597 }
ashleymills 0:714293de3836 1598 else if (id == ASN_COUNTRY_NAME) {
ashleymills 0:714293de3836 1599 if (!tooBig) {
ashleymills 0:714293de3836 1600 XMEMCPY(&full[idx], "/C=", 3);
ashleymills 0:714293de3836 1601 idx += 3;
ashleymills 0:714293de3836 1602 copy = TRUE;
ashleymills 0:714293de3836 1603 }
ashleymills 0:714293de3836 1604 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1605 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1606 cert->subjectC = (char*)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1607 cert->subjectCLen = strLen;
ashleymills 0:714293de3836 1608 }
ashleymills 0:714293de3836 1609 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1610 }
ashleymills 0:714293de3836 1611 else if (id == ASN_LOCALITY_NAME) {
ashleymills 0:714293de3836 1612 if (!tooBig) {
ashleymills 0:714293de3836 1613 XMEMCPY(&full[idx], "/L=", 3);
ashleymills 0:714293de3836 1614 idx += 3;
ashleymills 0:714293de3836 1615 copy = TRUE;
ashleymills 0:714293de3836 1616 }
ashleymills 0:714293de3836 1617 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1618 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1619 cert->subjectL = (char*)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1620 cert->subjectLLen = strLen;
ashleymills 0:714293de3836 1621 }
ashleymills 0:714293de3836 1622 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1623 }
ashleymills 0:714293de3836 1624 else if (id == ASN_STATE_NAME) {
ashleymills 0:714293de3836 1625 if (!tooBig) {
ashleymills 0:714293de3836 1626 XMEMCPY(&full[idx], "/ST=", 4);
ashleymills 0:714293de3836 1627 idx += 4;
ashleymills 0:714293de3836 1628 copy = TRUE;
ashleymills 0:714293de3836 1629 }
ashleymills 0:714293de3836 1630 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1631 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1632 cert->subjectST = (char*)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1633 cert->subjectSTLen = strLen;
ashleymills 0:714293de3836 1634 }
ashleymills 0:714293de3836 1635 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1636 }
ashleymills 0:714293de3836 1637 else if (id == ASN_ORG_NAME) {
ashleymills 0:714293de3836 1638 if (!tooBig) {
ashleymills 0:714293de3836 1639 XMEMCPY(&full[idx], "/O=", 3);
ashleymills 0:714293de3836 1640 idx += 3;
ashleymills 0:714293de3836 1641 copy = TRUE;
ashleymills 0:714293de3836 1642 }
ashleymills 0:714293de3836 1643 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1644 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1645 cert->subjectO = (char*)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1646 cert->subjectOLen = strLen;
ashleymills 0:714293de3836 1647 }
ashleymills 0:714293de3836 1648 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1649 }
ashleymills 0:714293de3836 1650 else if (id == ASN_ORGUNIT_NAME) {
ashleymills 0:714293de3836 1651 if (!tooBig) {
ashleymills 0:714293de3836 1652 XMEMCPY(&full[idx], "/OU=", 4);
ashleymills 0:714293de3836 1653 idx += 4;
ashleymills 0:714293de3836 1654 copy = TRUE;
ashleymills 0:714293de3836 1655 }
ashleymills 0:714293de3836 1656 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1657 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1658 cert->subjectOU = (char*)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1659 cert->subjectOULen = strLen;
ashleymills 0:714293de3836 1660 }
ashleymills 0:714293de3836 1661 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1662 }
ashleymills 0:714293de3836 1663
ashleymills 0:714293de3836 1664 if (copy && !tooBig) {
ashleymills 0:714293de3836 1665 XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
ashleymills 0:714293de3836 1666 idx += strLen;
ashleymills 0:714293de3836 1667 }
ashleymills 0:714293de3836 1668
ashleymills 0:714293de3836 1669 cert->srcIdx += strLen;
ashleymills 0:714293de3836 1670 }
ashleymills 0:714293de3836 1671 else {
ashleymills 0:714293de3836 1672 /* skip */
ashleymills 0:714293de3836 1673 byte email = FALSE;
ashleymills 0:714293de3836 1674 byte uid = FALSE;
ashleymills 0:714293de3836 1675 int adv;
ashleymills 0:714293de3836 1676
ashleymills 0:714293de3836 1677 if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */
ashleymills 0:714293de3836 1678 email = TRUE;
ashleymills 0:714293de3836 1679
ashleymills 0:714293de3836 1680 if (joint[0] == 0x9 && joint[1] == 0x92) /* uid id hdr */
ashleymills 0:714293de3836 1681 uid = TRUE;
ashleymills 0:714293de3836 1682
ashleymills 0:714293de3836 1683 cert->srcIdx += oidSz + 1;
ashleymills 0:714293de3836 1684
ashleymills 0:714293de3836 1685 if (GetLength(cert->source, &cert->srcIdx, &adv, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1686 return ASN_PARSE_E;
ashleymills 0:714293de3836 1687
ashleymills 0:714293de3836 1688 if (adv > (int)(ASN_NAME_MAX - idx)) {
ashleymills 0:714293de3836 1689 CYASSL_MSG("ASN name too big, skipping");
ashleymills 0:714293de3836 1690 tooBig = TRUE;
ashleymills 0:714293de3836 1691 }
ashleymills 0:714293de3836 1692
ashleymills 0:714293de3836 1693 if (email) {
ashleymills 0:714293de3836 1694 if ( (14 + adv) > (int)(ASN_NAME_MAX - idx)) {
ashleymills 0:714293de3836 1695 CYASSL_MSG("ASN name too big, skipping");
ashleymills 0:714293de3836 1696 tooBig = TRUE;
ashleymills 0:714293de3836 1697 }
ashleymills 0:714293de3836 1698 if (!tooBig) {
ashleymills 0:714293de3836 1699 XMEMCPY(&full[idx], "/emailAddress=", 14);
ashleymills 0:714293de3836 1700 idx += 14;
ashleymills 0:714293de3836 1701 }
ashleymills 0:714293de3836 1702
ashleymills 0:714293de3836 1703 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1704 if (nameType == SUBJECT) {
ashleymills 0:714293de3836 1705 cert->subjectEmail = (char*)&cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1706 cert->subjectEmailLen = adv;
ashleymills 0:714293de3836 1707 }
ashleymills 0:714293de3836 1708 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 1709
ashleymills 0:714293de3836 1710 if (!tooBig) {
ashleymills 0:714293de3836 1711 XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
ashleymills 0:714293de3836 1712 idx += adv;
ashleymills 0:714293de3836 1713 }
ashleymills 0:714293de3836 1714 }
ashleymills 0:714293de3836 1715
ashleymills 0:714293de3836 1716 if (uid) {
ashleymills 0:714293de3836 1717 if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) {
ashleymills 0:714293de3836 1718 CYASSL_MSG("ASN name too big, skipping");
ashleymills 0:714293de3836 1719 tooBig = TRUE;
ashleymills 0:714293de3836 1720 }
ashleymills 0:714293de3836 1721 if (!tooBig) {
ashleymills 0:714293de3836 1722 XMEMCPY(&full[idx], "/UID=", 5);
ashleymills 0:714293de3836 1723 idx += 5;
ashleymills 0:714293de3836 1724
ashleymills 0:714293de3836 1725 XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
ashleymills 0:714293de3836 1726 idx += adv;
ashleymills 0:714293de3836 1727 }
ashleymills 0:714293de3836 1728 }
ashleymills 0:714293de3836 1729
ashleymills 0:714293de3836 1730 cert->srcIdx += adv;
ashleymills 0:714293de3836 1731 }
ashleymills 0:714293de3836 1732 }
ashleymills 0:714293de3836 1733 full[idx++] = 0;
ashleymills 0:714293de3836 1734
ashleymills 0:714293de3836 1735 return 0;
ashleymills 0:714293de3836 1736 }
ashleymills 0:714293de3836 1737
ashleymills 0:714293de3836 1738
ashleymills 0:714293de3836 1739 #ifndef NO_TIME_H
ashleymills 0:714293de3836 1740
ashleymills 0:714293de3836 1741 /* to the second */
ashleymills 0:714293de3836 1742 static int DateGreaterThan(const struct tm* a, const struct tm* b)
ashleymills 0:714293de3836 1743 {
ashleymills 0:714293de3836 1744 if (a->tm_year > b->tm_year)
ashleymills 0:714293de3836 1745 return 1;
ashleymills 0:714293de3836 1746
ashleymills 0:714293de3836 1747 if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon)
ashleymills 0:714293de3836 1748 return 1;
ashleymills 0:714293de3836 1749
ashleymills 0:714293de3836 1750 if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
ashleymills 0:714293de3836 1751 a->tm_mday > b->tm_mday)
ashleymills 0:714293de3836 1752 return 1;
ashleymills 0:714293de3836 1753
ashleymills 0:714293de3836 1754 if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
ashleymills 0:714293de3836 1755 a->tm_mday == b->tm_mday && a->tm_hour > b->tm_hour)
ashleymills 0:714293de3836 1756 return 1;
ashleymills 0:714293de3836 1757
ashleymills 0:714293de3836 1758 if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
ashleymills 0:714293de3836 1759 a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
ashleymills 0:714293de3836 1760 a->tm_min > b->tm_min)
ashleymills 0:714293de3836 1761 return 1;
ashleymills 0:714293de3836 1762
ashleymills 0:714293de3836 1763 if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
ashleymills 0:714293de3836 1764 a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
ashleymills 0:714293de3836 1765 a->tm_min == b->tm_min && a->tm_sec > b->tm_sec)
ashleymills 0:714293de3836 1766 return 1;
ashleymills 0:714293de3836 1767
ashleymills 0:714293de3836 1768 return 0; /* false */
ashleymills 0:714293de3836 1769 }
ashleymills 0:714293de3836 1770
ashleymills 0:714293de3836 1771
ashleymills 0:714293de3836 1772 static INLINE int DateLessThan(const struct tm* a, const struct tm* b)
ashleymills 0:714293de3836 1773 {
ashleymills 0:714293de3836 1774 return !DateGreaterThan(a,b);
ashleymills 0:714293de3836 1775 }
ashleymills 0:714293de3836 1776
ashleymills 0:714293de3836 1777
ashleymills 0:714293de3836 1778 /* like atoi but only use first byte */
ashleymills 0:714293de3836 1779 /* Make sure before and after dates are valid */
ashleymills 0:714293de3836 1780 int ValidateDate(const byte* date, byte format, int dateType)
ashleymills 0:714293de3836 1781 {
ashleymills 0:714293de3836 1782 time_t ltime;
ashleymills 0:714293de3836 1783 struct tm certTime;
ashleymills 0:714293de3836 1784 struct tm* localTime;
ashleymills 0:714293de3836 1785 int i = 0;
ashleymills 0:714293de3836 1786
ashleymills 0:714293de3836 1787 ltime = XTIME(0);
ashleymills 0:714293de3836 1788
ashleymills 0:714293de3836 1789 XMEMSET(&certTime, 0, sizeof(certTime));
ashleymills 0:714293de3836 1790
ashleymills 0:714293de3836 1791 if (format == ASN_UTC_TIME) {
ashleymills 0:714293de3836 1792 if (btoi(date[0]) >= 5)
ashleymills 0:714293de3836 1793 certTime.tm_year = 1900;
ashleymills 0:714293de3836 1794 else
ashleymills 0:714293de3836 1795 certTime.tm_year = 2000;
ashleymills 0:714293de3836 1796 }
ashleymills 0:714293de3836 1797 else { /* format == GENERALIZED_TIME */
ashleymills 0:714293de3836 1798 certTime.tm_year += btoi(date[i++]) * 1000;
ashleymills 0:714293de3836 1799 certTime.tm_year += btoi(date[i++]) * 100;
ashleymills 0:714293de3836 1800 }
ashleymills 0:714293de3836 1801
ashleymills 0:714293de3836 1802 GetTime(&certTime.tm_year, date, &i); certTime.tm_year -= 1900; /* adjust */
ashleymills 0:714293de3836 1803 GetTime(&certTime.tm_mon, date, &i); certTime.tm_mon -= 1; /* adjust */
ashleymills 0:714293de3836 1804 GetTime(&certTime.tm_mday, date, &i);
ashleymills 0:714293de3836 1805 GetTime(&certTime.tm_hour, date, &i);
ashleymills 0:714293de3836 1806 GetTime(&certTime.tm_min, date, &i);
ashleymills 0:714293de3836 1807 GetTime(&certTime.tm_sec, date, &i);
ashleymills 0:714293de3836 1808
ashleymills 0:714293de3836 1809 if (date[i] != 'Z') { /* only Zulu supported for this profile */
ashleymills 0:714293de3836 1810 CYASSL_MSG("Only Zulu time supported for this profile");
ashleymills 0:714293de3836 1811 return 0;
ashleymills 0:714293de3836 1812 }
ashleymills 0:714293de3836 1813
ashleymills 0:714293de3836 1814 //localTime = XGMTIME(&ltime);
ashleymills 0:714293de3836 1815 // XXX gmtime seems to be broken on mbed, need to find out why
ashleymills 0:714293de3836 1816 localTime = localtime(&ltime);
ashleymills 0:714293de3836 1817
ashleymills 0:714293de3836 1818 if (dateType == BEFORE) {
ashleymills 0:714293de3836 1819 if (DateLessThan(localTime, &certTime))
ashleymills 0:714293de3836 1820 return 0;
ashleymills 0:714293de3836 1821 }
ashleymills 0:714293de3836 1822 else
ashleymills 0:714293de3836 1823 if (DateGreaterThan(localTime, &certTime))
ashleymills 0:714293de3836 1824 return 0;
ashleymills 0:714293de3836 1825
ashleymills 0:714293de3836 1826 return 1;
ashleymills 0:714293de3836 1827 }
ashleymills 0:714293de3836 1828
ashleymills 0:714293de3836 1829 #endif /* NO_TIME_H */
ashleymills 0:714293de3836 1830
ashleymills 0:714293de3836 1831
ashleymills 0:714293de3836 1832 static int GetDate(DecodedCert* cert, int dateType)
ashleymills 0:714293de3836 1833 {
ashleymills 0:714293de3836 1834 int length;
ashleymills 0:714293de3836 1835 byte date[MAX_DATE_SIZE];
ashleymills 0:714293de3836 1836 byte b;
ashleymills 0:714293de3836 1837
ashleymills 0:714293de3836 1838 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1839 word32 startIdx = 0;
ashleymills 0:714293de3836 1840 if (dateType == BEFORE)
ashleymills 0:714293de3836 1841 cert->beforeDate = &cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1842 else
ashleymills 0:714293de3836 1843 cert->afterDate = &cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1844 startIdx = cert->srcIdx;
ashleymills 0:714293de3836 1845 #endif
ashleymills 0:714293de3836 1846
ashleymills 0:714293de3836 1847 b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1848 if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME)
ashleymills 0:714293de3836 1849 return ASN_TIME_E;
ashleymills 0:714293de3836 1850
ashleymills 0:714293de3836 1851 if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1852 return ASN_PARSE_E;
ashleymills 0:714293de3836 1853
ashleymills 0:714293de3836 1854 if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
ashleymills 0:714293de3836 1855 return ASN_DATE_SZ_E;
ashleymills 0:714293de3836 1856
ashleymills 0:714293de3836 1857 XMEMCPY(date, &cert->source[cert->srcIdx], length);
ashleymills 0:714293de3836 1858 cert->srcIdx += length;
ashleymills 0:714293de3836 1859
ashleymills 0:714293de3836 1860 #ifdef CYASSL_CERT_GEN
ashleymills 0:714293de3836 1861 if (dateType == BEFORE)
ashleymills 0:714293de3836 1862 cert->beforeDateLen = cert->srcIdx - startIdx;
ashleymills 0:714293de3836 1863 else
ashleymills 0:714293de3836 1864 cert->afterDateLen = cert->srcIdx - startIdx;
ashleymills 0:714293de3836 1865 #endif
ashleymills 0:714293de3836 1866
ashleymills 0:714293de3836 1867 if (!XVALIDATE_DATE(date, b, dateType)) {
ashleymills 0:714293de3836 1868 if (dateType == BEFORE)
ashleymills 0:714293de3836 1869 return ASN_BEFORE_DATE_E;
ashleymills 0:714293de3836 1870 else
ashleymills 0:714293de3836 1871 return ASN_AFTER_DATE_E;
ashleymills 0:714293de3836 1872 }
ashleymills 0:714293de3836 1873
ashleymills 0:714293de3836 1874 return 0;
ashleymills 0:714293de3836 1875 }
ashleymills 0:714293de3836 1876
ashleymills 0:714293de3836 1877
ashleymills 0:714293de3836 1878 static int GetValidity(DecodedCert* cert, int verify)
ashleymills 0:714293de3836 1879 {
ashleymills 0:714293de3836 1880 int length;
ashleymills 0:714293de3836 1881 int badDate = 0;
ashleymills 0:714293de3836 1882
ashleymills 0:714293de3836 1883 if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1884 return ASN_PARSE_E;
ashleymills 0:714293de3836 1885
ashleymills 0:714293de3836 1886 if (GetDate(cert, BEFORE) < 0 && verify)
ashleymills 0:714293de3836 1887 badDate = ASN_BEFORE_DATE_E; /* continue parsing */
ashleymills 0:714293de3836 1888
ashleymills 0:714293de3836 1889 if (GetDate(cert, AFTER) < 0 && verify)
ashleymills 0:714293de3836 1890 return ASN_AFTER_DATE_E;
ashleymills 0:714293de3836 1891
ashleymills 0:714293de3836 1892 if (badDate != 0)
ashleymills 0:714293de3836 1893 return badDate;
ashleymills 0:714293de3836 1894
ashleymills 0:714293de3836 1895 return 0;
ashleymills 0:714293de3836 1896 }
ashleymills 0:714293de3836 1897
ashleymills 0:714293de3836 1898
ashleymills 0:714293de3836 1899 int DecodeToKey(DecodedCert* cert, int verify)
ashleymills 0:714293de3836 1900 {
ashleymills 0:714293de3836 1901 int badDate = 0;
ashleymills 0:714293de3836 1902 int ret;
ashleymills 0:714293de3836 1903
ashleymills 0:714293de3836 1904 if ( (ret = GetCertHeader(cert)) < 0)
ashleymills 0:714293de3836 1905 return ret;
ashleymills 0:714293de3836 1906
ashleymills 0:714293de3836 1907 if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
ashleymills 0:714293de3836 1908 cert->maxIdx)) < 0)
ashleymills 0:714293de3836 1909 return ret;
ashleymills 0:714293de3836 1910
ashleymills 0:714293de3836 1911 if ( (ret = GetName(cert, ISSUER)) < 0)
ashleymills 0:714293de3836 1912 return ret;
ashleymills 0:714293de3836 1913
ashleymills 0:714293de3836 1914 if ( (ret = GetValidity(cert, verify)) < 0)
ashleymills 0:714293de3836 1915 badDate = ret;
ashleymills 0:714293de3836 1916
ashleymills 0:714293de3836 1917 if ( (ret = GetName(cert, SUBJECT)) < 0)
ashleymills 0:714293de3836 1918 return ret;
ashleymills 0:714293de3836 1919
ashleymills 0:714293de3836 1920 if ( (ret = GetKey(cert)) < 0)
ashleymills 0:714293de3836 1921 return ret;
ashleymills 0:714293de3836 1922
ashleymills 0:714293de3836 1923 if (badDate != 0)
ashleymills 0:714293de3836 1924 return badDate;
ashleymills 0:714293de3836 1925
ashleymills 0:714293de3836 1926 return ret;
ashleymills 0:714293de3836 1927 }
ashleymills 0:714293de3836 1928
ashleymills 0:714293de3836 1929
ashleymills 0:714293de3836 1930 static int GetSignature(DecodedCert* cert)
ashleymills 0:714293de3836 1931 {
ashleymills 0:714293de3836 1932 int length;
ashleymills 0:714293de3836 1933 byte b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1934
ashleymills 0:714293de3836 1935 if (b != ASN_BIT_STRING)
ashleymills 0:714293de3836 1936 return ASN_BITSTR_E;
ashleymills 0:714293de3836 1937
ashleymills 0:714293de3836 1938 if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
ashleymills 0:714293de3836 1939 return ASN_PARSE_E;
ashleymills 0:714293de3836 1940
ashleymills 0:714293de3836 1941 cert->sigLength = length;
ashleymills 0:714293de3836 1942
ashleymills 0:714293de3836 1943 b = cert->source[cert->srcIdx++];
ashleymills 0:714293de3836 1944 if (b != 0x00)
ashleymills 0:714293de3836 1945 return ASN_EXPECT_0_E;
ashleymills 0:714293de3836 1946
ashleymills 0:714293de3836 1947 cert->sigLength--;
ashleymills 0:714293de3836 1948 cert->signature = &cert->source[cert->srcIdx];
ashleymills 0:714293de3836 1949 cert->srcIdx += cert->sigLength;
ashleymills 0:714293de3836 1950
ashleymills 0:714293de3836 1951 return 0;
ashleymills 0:714293de3836 1952 }
ashleymills 0:714293de3836 1953
ashleymills 0:714293de3836 1954
ashleymills 0:714293de3836 1955 static word32 SetDigest(const byte* digest, word32 digSz, byte* output)
ashleymills 0:714293de3836 1956 {
ashleymills 0:714293de3836 1957 output[0] = ASN_OCTET_STRING;
ashleymills 0:714293de3836 1958 output[1] = (byte)digSz;
ashleymills 0:714293de3836 1959 XMEMCPY(&output[2], digest, digSz);
ashleymills 0:714293de3836 1960
ashleymills 0:714293de3836 1961 return digSz + 2;
ashleymills 0:714293de3836 1962 }
ashleymills 0:714293de3836 1963
ashleymills 0:714293de3836 1964
ashleymills 0:714293de3836 1965 static word32 BytePrecision(word32 value)
ashleymills 0:714293de3836 1966 {
ashleymills 0:714293de3836 1967 word32 i;
ashleymills 0:714293de3836 1968 for (i = sizeof(value); i; --i)
ashleymills 0:714293de3836 1969 if (value >> ((i - 1) * CYASSL_BIT_SIZE))
ashleymills 0:714293de3836 1970 break;
ashleymills 0:714293de3836 1971
ashleymills 0:714293de3836 1972 return i;
ashleymills 0:714293de3836 1973 }
ashleymills 0:714293de3836 1974
ashleymills 0:714293de3836 1975
ashleymills 0:714293de3836 1976 static word32 SetLength(word32 length, byte* output)
ashleymills 0:714293de3836 1977 {
ashleymills 0:714293de3836 1978 word32 i = 0, j;
ashleymills 0:714293de3836 1979
ashleymills 0:714293de3836 1980 if (length < ASN_LONG_LENGTH)
ashleymills 0:714293de3836 1981 output[i++] = (byte)length;
ashleymills 0:714293de3836 1982 else {
ashleymills 0:714293de3836 1983 output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
ashleymills 0:714293de3836 1984
ashleymills 0:714293de3836 1985 for (j = BytePrecision(length); j; --j) {
ashleymills 0:714293de3836 1986 output[i] = (byte)(length >> ((j - 1) * CYASSL_BIT_SIZE));
ashleymills 0:714293de3836 1987 i++;
ashleymills 0:714293de3836 1988 }
ashleymills 0:714293de3836 1989 }
ashleymills 0:714293de3836 1990
ashleymills 0:714293de3836 1991 return i;
ashleymills 0:714293de3836 1992 }
ashleymills 0:714293de3836 1993
ashleymills 0:714293de3836 1994
ashleymills 0:714293de3836 1995 static word32 SetSequence(word32 len, byte* output)
ashleymills 0:714293de3836 1996 {
ashleymills 0:714293de3836 1997 output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
ashleymills 0:714293de3836 1998 return SetLength(len, output + 1) + 1;
ashleymills 0:714293de3836 1999 }
ashleymills 0:714293de3836 2000
ashleymills 0:714293de3836 2001
ashleymills 0:714293de3836 2002 static word32 SetAlgoID(int algoOID, byte* output, int type)
ashleymills 0:714293de3836 2003 {
ashleymills 0:714293de3836 2004 /* adding TAG_NULL and 0 to end */
ashleymills 0:714293de3836 2005
ashleymills 0:714293de3836 2006 /* hashTypes */
ashleymills 0:714293de3836 2007 static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
ashleymills 0:714293de3836 2008 0x05, 0x00 };
ashleymills 0:714293de3836 2009 static const byte sha256AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
ashleymills 0:714293de3836 2010 0x04, 0x02, 0x01, 0x05, 0x00 };
ashleymills 0:714293de3836 2011 static const byte sha384AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
ashleymills 0:714293de3836 2012 0x04, 0x02, 0x02, 0x05, 0x00 };
ashleymills 0:714293de3836 2013 static const byte sha512AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
ashleymills 0:714293de3836 2014 0x04, 0x02, 0x03, 0x05, 0x00 };
ashleymills 0:714293de3836 2015 static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
ashleymills 0:714293de3836 2016 0x02, 0x05, 0x05, 0x00 };
ashleymills 0:714293de3836 2017 static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
ashleymills 0:714293de3836 2018 0x02, 0x02, 0x05, 0x00};
ashleymills 0:714293de3836 2019
ashleymills 0:714293de3836 2020 /* sigTypes */
ashleymills 0:714293de3836 2021 #ifndef NO_RSA
ashleymills 0:714293de3836 2022 static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
ashleymills 0:714293de3836 2023 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00};
ashleymills 0:714293de3836 2024 static const byte shawRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
ashleymills 0:714293de3836 2025 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00};
ashleymills 0:714293de3836 2026 static const byte sha256wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
ashleymills 0:714293de3836 2027 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00};
ashleymills 0:714293de3836 2028 static const byte sha384wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
ashleymills 0:714293de3836 2029 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00};
ashleymills 0:714293de3836 2030 static const byte sha512wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
ashleymills 0:714293de3836 2031 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00};
ashleymills 0:714293de3836 2032 #endif /* NO_RSA */
ashleymills 0:714293de3836 2033
ashleymills 0:714293de3836 2034 /* keyTypes */
ashleymills 0:714293de3836 2035 #ifndef NO_RSA
ashleymills 0:714293de3836 2036 static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
ashleymills 0:714293de3836 2037 0x01, 0x01, 0x01, 0x05, 0x00};
ashleymills 0:714293de3836 2038 #endif /* NO_RSA */
ashleymills 0:714293de3836 2039
ashleymills 0:714293de3836 2040 int algoSz = 0;
ashleymills 0:714293de3836 2041 word32 idSz, seqSz;
ashleymills 0:714293de3836 2042 const byte* algoName = 0;
ashleymills 0:714293de3836 2043 byte ID_Length[MAX_LENGTH_SZ];
ashleymills 0:714293de3836 2044 byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
ashleymills 0:714293de3836 2045
ashleymills 0:714293de3836 2046 if (type == hashType) {
ashleymills 0:714293de3836 2047 switch (algoOID) {
ashleymills 0:714293de3836 2048 case SHAh:
ashleymills 0:714293de3836 2049 algoSz = sizeof(shaAlgoID);
ashleymills 0:714293de3836 2050 algoName = shaAlgoID;
ashleymills 0:714293de3836 2051 break;
ashleymills 0:714293de3836 2052
ashleymills 0:714293de3836 2053 case SHA256h:
ashleymills 0:714293de3836 2054 algoSz = sizeof(sha256AlgoID);
ashleymills 0:714293de3836 2055 algoName = sha256AlgoID;
ashleymills 0:714293de3836 2056 break;
ashleymills 0:714293de3836 2057
ashleymills 0:714293de3836 2058 case SHA384h:
ashleymills 0:714293de3836 2059 algoSz = sizeof(sha384AlgoID);
ashleymills 0:714293de3836 2060 algoName = sha384AlgoID;
ashleymills 0:714293de3836 2061 break;
ashleymills 0:714293de3836 2062
ashleymills 0:714293de3836 2063 case SHA512h:
ashleymills 0:714293de3836 2064 algoSz = sizeof(sha512AlgoID);
ashleymills 0:714293de3836 2065 algoName = sha512AlgoID;
ashleymills 0:714293de3836 2066 break;
ashleymills 0:714293de3836 2067
ashleymills 0:714293de3836 2068 case MD2h:
ashleymills 0:714293de3836 2069 algoSz = sizeof(md2AlgoID);
ashleymills 0:714293de3836 2070 algoName = md2AlgoID;
ashleymills 0:714293de3836 2071 break;
ashleymills 0:714293de3836 2072
ashleymills 0:714293de3836 2073 case MD5h:
ashleymills 0:714293de3836 2074 algoSz = sizeof(md5AlgoID);
ashleymills 0:714293de3836 2075 algoName = md5AlgoID;
ashleymills 0:714293de3836 2076 break;
ashleymills 0:714293de3836 2077
ashleymills 0:714293de3836 2078 default:
ashleymills 0:714293de3836 2079 CYASSL_MSG("Unknown Hash Algo");
ashleymills 0:714293de3836 2080 return 0; /* UNKOWN_HASH_E; */
ashleymills 0:714293de3836 2081 }
ashleymills 0:714293de3836 2082 }
ashleymills 0:714293de3836 2083 else if (type == sigType) { /* sigType */
ashleymills 0:714293de3836 2084 switch (algoOID) {
ashleymills 0:714293de3836 2085 #ifndef NO_RSA
ashleymills 0:714293de3836 2086 case CTC_MD5wRSA:
ashleymills 0:714293de3836 2087 algoSz = sizeof(md5wRSA_AlgoID);
ashleymills 0:714293de3836 2088 algoName = md5wRSA_AlgoID;
ashleymills 0:714293de3836 2089 break;
ashleymills 0:714293de3836 2090
ashleymills 0:714293de3836 2091 case CTC_SHAwRSA:
ashleymills 0:714293de3836 2092 algoSz = sizeof(shawRSA_AlgoID);
ashleymills 0:714293de3836 2093 algoName = shawRSA_AlgoID;
ashleymills 0:714293de3836 2094 break;
ashleymills 0:714293de3836 2095
ashleymills 0:714293de3836 2096 case CTC_SHA256wRSA:
ashleymills 0:714293de3836 2097 algoSz = sizeof(sha256wRSA_AlgoID);
ashleymills 0:714293de3836 2098 algoName = sha256wRSA_AlgoID;
ashleymills 0:714293de3836 2099 break;
ashleymills 0:714293de3836 2100
ashleymills 0:714293de3836 2101 case CTC_SHA384wRSA:
ashleymills 0:714293de3836 2102 algoSz = sizeof(sha384wRSA_AlgoID);
ashleymills 0:714293de3836 2103 algoName = sha384wRSA_AlgoID;
ashleymills 0:714293de3836 2104 break;
ashleymills 0:714293de3836 2105
ashleymills 0:714293de3836 2106 case CTC_SHA512wRSA:
ashleymills 0:714293de3836 2107 algoSz = sizeof(sha512wRSA_AlgoID);
ashleymills 0:714293de3836 2108 algoName = sha512wRSA_AlgoID;
ashleymills 0:714293de3836 2109 break;
ashleymills 0:714293de3836 2110 #endif /* NO_RSA */
ashleymills 0:714293de3836 2111 default:
ashleymills 0:714293de3836 2112 CYASSL_MSG("Unknown Signature Algo");
ashleymills 0:714293de3836 2113 return 0;
ashleymills 0:714293de3836 2114 }
ashleymills 0:714293de3836 2115 }
ashleymills 0:714293de3836 2116 else if (type == keyType) { /* keyType */
ashleymills 0:714293de3836 2117 switch (algoOID) {
ashleymills 0:714293de3836 2118 #ifndef NO_RSA
ashleymills 0:714293de3836 2119 case RSAk:
ashleymills 0:714293de3836 2120 algoSz = sizeof(RSA_AlgoID);
ashleymills 0:714293de3836 2121 algoName = RSA_AlgoID;
ashleymills 0:714293de3836 2122 break;
ashleymills 0:714293de3836 2123 #endif /* NO_RSA */
ashleymills 0:714293de3836 2124 default:
ashleymills 0:714293de3836 2125 CYASSL_MSG("Unknown Key Algo");
ashleymills 0:714293de3836 2126 return 0;
ashleymills 0:714293de3836 2127 }
ashleymills 0:714293de3836 2128 }
ashleymills 0:714293de3836 2129 else {
ashleymills 0:714293de3836 2130 CYASSL_MSG("Unknown Algo type");
ashleymills 0:714293de3836 2131 return 0;
ashleymills 0:714293de3836 2132 }
ashleymills 0:714293de3836 2133
ashleymills 0:714293de3836 2134 idSz = SetLength(algoSz - 2, ID_Length); /* don't include TAG_NULL/0 */
ashleymills 0:714293de3836 2135 seqSz = SetSequence(idSz + algoSz + 1, seqArray);
ashleymills 0:714293de3836 2136 seqArray[seqSz++] = ASN_OBJECT_ID;
ashleymills 0:714293de3836 2137
ashleymills 0:714293de3836 2138 XMEMCPY(output, seqArray, seqSz);
ashleymills 0:714293de3836 2139 XMEMCPY(output + seqSz, ID_Length, idSz);
ashleymills 0:714293de3836 2140 XMEMCPY(output + seqSz + idSz, algoName, algoSz);
ashleymills 0:714293de3836 2141
ashleymills 0:714293de3836 2142 return seqSz + idSz + algoSz;
ashleymills 0:714293de3836 2143
ashleymills 0:714293de3836 2144 }
ashleymills 0:714293de3836 2145
ashleymills 0:714293de3836 2146
ashleymills 0:714293de3836 2147 word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID)
ashleymills 0:714293de3836 2148 {
ashleymills 0:714293de3836 2149 byte digArray[MAX_ENCODED_DIG_SZ];
ashleymills 0:714293de3836 2150 byte algoArray[MAX_ALGO_SZ];
ashleymills 0:714293de3836 2151 byte seqArray[MAX_SEQ_SZ];
ashleymills 0:714293de3836 2152 word32 encDigSz, algoSz, seqSz;
ashleymills 0:714293de3836 2153
ashleymills 0:714293de3836 2154 encDigSz = SetDigest(digest, digSz, digArray);
ashleymills 0:714293de3836 2155 algoSz = SetAlgoID(hashOID, algoArray, hashType);
ashleymills 0:714293de3836 2156 seqSz = SetSequence(encDigSz + algoSz, seqArray);
ashleymills 0:714293de3836 2157
ashleymills 0:714293de3836 2158 XMEMCPY(out, seqArray, seqSz);
ashleymills 0:714293de3836 2159 XMEMCPY(out + seqSz, algoArray, algoSz);
ashleymills 0:714293de3836 2160 XMEMCPY(out + seqSz + algoSz, digArray, encDigSz);
ashleymills 0:714293de3836 2161
ashleymills 0:714293de3836 2162 return encDigSz + algoSz + seqSz;
ashleymills 0:714293de3836 2163 }
ashleymills 0:714293de3836 2164
ashleymills 0:714293de3836 2165
ashleymills 0:714293de3836 2166 /* return true (1) for Confirmation */
ashleymills 0:714293de3836 2167 static int ConfirmSignature(const byte* buf, word32 bufSz,
ashleymills 0:714293de3836 2168 const byte* key, word32 keySz, word32 keyOID,
ashleymills 0:714293de3836 2169 const byte* sig, word32 sigSz, word32 sigOID,
ashleymills 0:714293de3836 2170 void* heap)
ashleymills 0:714293de3836 2171 {
ashleymills 0:714293de3836 2172 #ifdef CYASSL_SHA512
ashleymills 0:714293de3836 2173 byte digest[SHA512_DIGEST_SIZE]; /* max size */
ashleymills 0:714293de3836 2174 #elif !defined(NO_SHA256)
ashleymills 0:714293de3836 2175 byte digest[SHA256_DIGEST_SIZE]; /* max size */
ashleymills 0:714293de3836 2176 #else
ashleymills 0:714293de3836 2177 byte digest[SHA_DIGEST_SIZE]; /* max size */
ashleymills 0:714293de3836 2178 #endif
ashleymills 0:714293de3836 2179 int typeH, digestSz, ret = 0;
ashleymills 0:714293de3836 2180
ashleymills 0:714293de3836 2181 (void)key;
ashleymills 0:714293de3836 2182 (void)keySz;
ashleymills 0:714293de3836 2183 (void)sig;
ashleymills 0:714293de3836 2184 (void)sigSz;
ashleymills 0:714293de3836 2185 (void)heap;
ashleymills 0:714293de3836 2186 (void)ret;
ashleymills 0:714293de3836 2187
ashleymills 0:714293de3836 2188 switch (sigOID) {
ashleymills 0:714293de3836 2189 #ifndef NO_MD5
ashleymills 0:714293de3836 2190 case CTC_MD5wRSA:
ashleymills 0:714293de3836 2191 {
ashleymills 0:714293de3836 2192 Md5 md5;
ashleymills 0:714293de3836 2193 InitMd5(&md5);
ashleymills 0:714293de3836 2194 Md5Update(&md5, buf, bufSz);
ashleymills 0:714293de3836 2195 Md5Final(&md5, digest);
ashleymills 0:714293de3836 2196 typeH = MD5h;
ashleymills 0:714293de3836 2197 digestSz = MD5_DIGEST_SIZE;
ashleymills 0:714293de3836 2198 }
ashleymills 0:714293de3836 2199 break;
ashleymills 0:714293de3836 2200 #endif
ashleymills 0:714293de3836 2201 #if defined(CYASSL_MD2)
ashleymills 0:714293de3836 2202 case CTC_MD2wRSA:
ashleymills 0:714293de3836 2203 {
ashleymills 0:714293de3836 2204 Md2 md2;
ashleymills 0:714293de3836 2205 InitMd2(&md2);
ashleymills 0:714293de3836 2206 Md2Update(&md2, buf, bufSz);
ashleymills 0:714293de3836 2207 Md2Final(&md2, digest);
ashleymills 0:714293de3836 2208 typeH = MD2h;
ashleymills 0:714293de3836 2209 digestSz = MD2_DIGEST_SIZE;
ashleymills 0:714293de3836 2210 }
ashleymills 0:714293de3836 2211 break;
ashleymills 0:714293de3836 2212 #endif
ashleymills 0:714293de3836 2213 #ifndef NO_SHA
ashleymills 0:714293de3836 2214 case CTC_SHAwRSA:
ashleymills 0:714293de3836 2215 case CTC_SHAwDSA:
ashleymills 0:714293de3836 2216 case CTC_SHAwECDSA:
ashleymills 0:714293de3836 2217 {
ashleymills 0:714293de3836 2218 Sha sha;
ashleymills 0:714293de3836 2219 InitSha(&sha);
ashleymills 0:714293de3836 2220 ShaUpdate(&sha, buf, bufSz);
ashleymills 0:714293de3836 2221 ShaFinal(&sha, digest);
ashleymills 0:714293de3836 2222 typeH = SHAh;
ashleymills 0:714293de3836 2223 digestSz = SHA_DIGEST_SIZE;
ashleymills 0:714293de3836 2224 }
ashleymills 0:714293de3836 2225 break;
ashleymills 0:714293de3836 2226 #endif
ashleymills 0:714293de3836 2227 #ifndef NO_SHA256
ashleymills 0:714293de3836 2228 case CTC_SHA256wRSA:
ashleymills 0:714293de3836 2229 case CTC_SHA256wECDSA:
ashleymills 0:714293de3836 2230 {
ashleymills 0:714293de3836 2231 Sha256 sha256;
ashleymills 0:714293de3836 2232 InitSha256(&sha256);
ashleymills 0:714293de3836 2233 Sha256Update(&sha256, buf, bufSz);
ashleymills 0:714293de3836 2234 Sha256Final(&sha256, digest);
ashleymills 0:714293de3836 2235 typeH = SHA256h;
ashleymills 0:714293de3836 2236 digestSz = SHA256_DIGEST_SIZE;
ashleymills 0:714293de3836 2237 }
ashleymills 0:714293de3836 2238 break;
ashleymills 0:714293de3836 2239 #endif
ashleymills 0:714293de3836 2240 #ifdef CYASSL_SHA512
ashleymills 0:714293de3836 2241 case CTC_SHA512wRSA:
ashleymills 0:714293de3836 2242 case CTC_SHA512wECDSA:
ashleymills 0:714293de3836 2243 {
ashleymills 0:714293de3836 2244 Sha512 sha512;
ashleymills 0:714293de3836 2245 InitSha512(&sha512);
ashleymills 0:714293de3836 2246 Sha512Update(&sha512, buf, bufSz);
ashleymills 0:714293de3836 2247 Sha512Final(&sha512, digest);
ashleymills 0:714293de3836 2248 typeH = SHA512h;
ashleymills 0:714293de3836 2249 digestSz = SHA512_DIGEST_SIZE;
ashleymills 0:714293de3836 2250 }
ashleymills 0:714293de3836 2251 break;
ashleymills 0:714293de3836 2252 #endif
ashleymills 0:714293de3836 2253 #ifdef CYASSL_SHA384
ashleymills 0:714293de3836 2254 case CTC_SHA384wRSA:
ashleymills 0:714293de3836 2255 case CTC_SHA384wECDSA:
ashleymills 0:714293de3836 2256 {
ashleymills 0:714293de3836 2257 Sha384 sha384;
ashleymills 0:714293de3836 2258 InitSha384(&sha384);
ashleymills 0:714293de3836 2259 Sha384Update(&sha384, buf, bufSz);
ashleymills 0:714293de3836 2260 Sha384Final(&sha384, digest);
ashleymills 0:714293de3836 2261 typeH = SHA384h;
ashleymills 0:714293de3836 2262 digestSz = SHA384_DIGEST_SIZE;
ashleymills 0:714293de3836 2263 }
ashleymills 0:714293de3836 2264 break;
ashleymills 0:714293de3836 2265 #endif
ashleymills 0:714293de3836 2266 default:
ashleymills 0:714293de3836 2267 CYASSL_MSG("Verify Signautre has unsupported type");
ashleymills 0:714293de3836 2268 return 0;
ashleymills 0:714293de3836 2269 }
ashleymills 0:714293de3836 2270
ashleymills 0:714293de3836 2271 switch (keyOID) {
ashleymills 0:714293de3836 2272 #ifndef NO_RSA
ashleymills 0:714293de3836 2273 case RSAk:
ashleymills 0:714293de3836 2274 {
ashleymills 0:714293de3836 2275 RsaKey pubKey;
ashleymills 0:714293de3836 2276 byte encodedSig[MAX_ENCODED_SIG_SZ];
ashleymills 0:714293de3836 2277 byte plain[MAX_ENCODED_SIG_SZ];
ashleymills 0:714293de3836 2278 word32 idx = 0;
ashleymills 0:714293de3836 2279 int encodedSigSz, verifySz;
ashleymills 0:714293de3836 2280 byte* out;
ashleymills 0:714293de3836 2281
ashleymills 0:714293de3836 2282 if (sigSz > MAX_ENCODED_SIG_SZ) {
ashleymills 0:714293de3836 2283 CYASSL_MSG("Verify Signautre is too big");
ashleymills 0:714293de3836 2284 return 0;
ashleymills 0:714293de3836 2285 }
ashleymills 0:714293de3836 2286
ashleymills 0:714293de3836 2287 InitRsaKey(&pubKey, heap);
ashleymills 0:714293de3836 2288 if (RsaPublicKeyDecode(key, &idx, &pubKey, keySz) < 0) {
ashleymills 0:714293de3836 2289 CYASSL_MSG("ASN Key decode error RSA");
ashleymills 0:714293de3836 2290 ret = 0;
ashleymills 0:714293de3836 2291 }
ashleymills 0:714293de3836 2292 else {
ashleymills 0:714293de3836 2293 XMEMCPY(plain, sig, sigSz);
ashleymills 0:714293de3836 2294 if ( (verifySz = RsaSSL_VerifyInline(plain, sigSz, &out,
ashleymills 0:714293de3836 2295 &pubKey)) < 0) {
ashleymills 0:714293de3836 2296 CYASSL_MSG("Rsa SSL verify error");
ashleymills 0:714293de3836 2297 ret = 0;
ashleymills 0:714293de3836 2298 }
ashleymills 0:714293de3836 2299 else {
ashleymills 0:714293de3836 2300 /* make sure we're right justified */
ashleymills 0:714293de3836 2301 encodedSigSz =
ashleymills 0:714293de3836 2302 EncodeSignature(encodedSig, digest, digestSz, typeH);
ashleymills 0:714293de3836 2303 if (encodedSigSz != verifySz ||
ashleymills 0:714293de3836 2304 XMEMCMP(out, encodedSig, encodedSigSz) != 0) {
ashleymills 0:714293de3836 2305 CYASSL_MSG("Rsa SSL verify match encode error");
ashleymills 0:714293de3836 2306 ret = 0;
ashleymills 0:714293de3836 2307 }
ashleymills 0:714293de3836 2308 else
ashleymills 0:714293de3836 2309 ret = 1; /* match */
ashleymills 0:714293de3836 2310
ashleymills 0:714293de3836 2311 #ifdef CYASSL_DEBUG_ENCODING
ashleymills 0:714293de3836 2312 {
ashleymills 0:714293de3836 2313 int x;
ashleymills 0:714293de3836 2314 printf("cyassl encodedSig:\n");
ashleymills 0:714293de3836 2315 for (x = 0; x < encodedSigSz; x++) {
ashleymills 0:714293de3836 2316 printf("%02x ", encodedSig[x]);
ashleymills 0:714293de3836 2317 if ( (x % 16) == 15)
ashleymills 0:714293de3836 2318 printf("\n");
ashleymills 0:714293de3836 2319 }
ashleymills 0:714293de3836 2320 printf("\n");
ashleymills 0:714293de3836 2321 printf("actual digest:\n");
ashleymills 0:714293de3836 2322 for (x = 0; x < verifySz; x++) {
ashleymills 0:714293de3836 2323 printf("%02x ", out[x]);
ashleymills 0:714293de3836 2324 if ( (x % 16) == 15)
ashleymills 0:714293de3836 2325 printf("\n");
ashleymills 0:714293de3836 2326 }
ashleymills 0:714293de3836 2327 printf("\n");
ashleymills 0:714293de3836 2328 }
ashleymills 0:714293de3836 2329 #endif /* CYASSL_DEBUG_ENCODING */
ashleymills 0:714293de3836 2330 }
ashleymills 0:714293de3836 2331 }
ashleymills 0:714293de3836 2332 FreeRsaKey(&pubKey);
ashleymills 0:714293de3836 2333 return ret;
ashleymills 0:714293de3836 2334 }
ashleymills 0:714293de3836 2335
ashleymills 0:714293de3836 2336 #endif /* NO_RSA */
ashleymills 0:714293de3836 2337 #ifdef HAVE_ECC
ashleymills 0:714293de3836 2338 case ECDSAk:
ashleymills 0:714293de3836 2339 {
ashleymills 0:714293de3836 2340 ecc_key pubKey;
ashleymills 0:714293de3836 2341 int verify = 0;
ashleymills 0:714293de3836 2342
ashleymills 0:714293de3836 2343 if (ecc_import_x963(key, keySz, &pubKey) < 0) {
ashleymills 0:714293de3836 2344 CYASSL_MSG("ASN Key import error ECC");
ashleymills 0:714293de3836 2345 return 0;
ashleymills 0:714293de3836 2346 }
ashleymills 0:714293de3836 2347
ashleymills 0:714293de3836 2348 ret = ecc_verify_hash(sig,sigSz,digest,digestSz,&verify,&pubKey);
ashleymills 0:714293de3836 2349 ecc_free(&pubKey);
ashleymills 0:714293de3836 2350 if (ret == 0 && verify == 1)
ashleymills 0:714293de3836 2351 return 1; /* match */
ashleymills 0:714293de3836 2352
ashleymills 0:714293de3836 2353 CYASSL_MSG("ECC Verify didn't match");
ashleymills 0:714293de3836 2354 return 0;
ashleymills 0:714293de3836 2355 }
ashleymills 0:714293de3836 2356 #endif /* HAVE_ECC */
ashleymills 0:714293de3836 2357 default:
ashleymills 0:714293de3836 2358 CYASSL_MSG("Verify Key type unknown");
ashleymills 0:714293de3836 2359 return 0;
ashleymills 0:714293de3836 2360 }
ashleymills 0:714293de3836 2361 }
ashleymills 0:714293de3836 2362
ashleymills 0:714293de3836 2363
ashleymills 0:714293de3836 2364 static void DecodeAltNames(byte* input, int sz, DecodedCert* cert)
ashleymills 0:714293de3836 2365 {
ashleymills 0:714293de3836 2366 word32 idx = 0;
ashleymills 0:714293de3836 2367 int length = 0;
ashleymills 0:714293de3836 2368
ashleymills 0:714293de3836 2369 CYASSL_ENTER("DecodeAltNames");
ashleymills 0:714293de3836 2370
ashleymills 0:714293de3836 2371 if (GetSequence(input, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 2372 CYASSL_MSG("\tBad Sequence");
ashleymills 0:714293de3836 2373 return;
ashleymills 0:714293de3836 2374 }
ashleymills 0:714293de3836 2375
ashleymills 0:714293de3836 2376 while (length > 0) {
ashleymills 0:714293de3836 2377 DNS_entry* entry;
ashleymills 0:714293de3836 2378 int strLen;
ashleymills 0:714293de3836 2379 byte b = input[idx++];
ashleymills 0:714293de3836 2380
ashleymills 0:714293de3836 2381 length--;
ashleymills 0:714293de3836 2382
ashleymills 0:714293de3836 2383 if (b != (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE)) {
ashleymills 0:714293de3836 2384 CYASSL_MSG("\tNot DNS type");
ashleymills 0:714293de3836 2385 return;
ashleymills 0:714293de3836 2386 }
ashleymills 0:714293de3836 2387
ashleymills 0:714293de3836 2388 if (GetLength(input, &idx, &strLen, sz) < 0) {
ashleymills 0:714293de3836 2389 CYASSL_MSG("\tfail: str length");
ashleymills 0:714293de3836 2390 return;
ashleymills 0:714293de3836 2391 }
ashleymills 0:714293de3836 2392
ashleymills 0:714293de3836 2393 entry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
ashleymills 0:714293de3836 2394 DYNAMIC_TYPE_ALTNAME);
ashleymills 0:714293de3836 2395 if (entry == NULL) {
ashleymills 0:714293de3836 2396 CYASSL_MSG("\tOut of Memory");
ashleymills 0:714293de3836 2397 return;
ashleymills 0:714293de3836 2398 }
ashleymills 0:714293de3836 2399
ashleymills 0:714293de3836 2400 entry->name = (char*)XMALLOC(strLen + 1, cert->heap,
ashleymills 0:714293de3836 2401 DYNAMIC_TYPE_ALTNAME);
ashleymills 0:714293de3836 2402 if (entry->name == NULL) {
ashleymills 0:714293de3836 2403 CYASSL_MSG("\tOut of Memory");
ashleymills 0:714293de3836 2404 XFREE(entry, cert->heap, DYNAMIC_TYPE_ALTNAME);
ashleymills 0:714293de3836 2405 return;
ashleymills 0:714293de3836 2406 }
ashleymills 0:714293de3836 2407
ashleymills 0:714293de3836 2408 XMEMCPY(entry->name, &input[idx], strLen);
ashleymills 0:714293de3836 2409 entry->name[strLen] = '\0';
ashleymills 0:714293de3836 2410
ashleymills 0:714293de3836 2411 entry->next = cert->altNames;
ashleymills 0:714293de3836 2412 cert->altNames = entry;
ashleymills 0:714293de3836 2413
ashleymills 0:714293de3836 2414 length -= strLen;
ashleymills 0:714293de3836 2415 idx += strLen;
ashleymills 0:714293de3836 2416 }
ashleymills 0:714293de3836 2417 }
ashleymills 0:714293de3836 2418
ashleymills 0:714293de3836 2419
ashleymills 0:714293de3836 2420 static void DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
ashleymills 0:714293de3836 2421 {
ashleymills 0:714293de3836 2422 word32 idx = 0;
ashleymills 0:714293de3836 2423 int length = 0;
ashleymills 0:714293de3836 2424
ashleymills 0:714293de3836 2425 CYASSL_ENTER("DecodeBasicCaConstraint");
ashleymills 0:714293de3836 2426 if (GetSequence(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2427
ashleymills 0:714293de3836 2428 if (length == 0) return;
ashleymills 0:714293de3836 2429 /* If the basic ca constraint is false, this extension may be named, but
ashleymills 0:714293de3836 2430 * left empty. So, if the length is 0, just return. */
ashleymills 0:714293de3836 2431
ashleymills 0:714293de3836 2432 if (input[idx++] != ASN_BOOLEAN)
ashleymills 0:714293de3836 2433 {
ashleymills 0:714293de3836 2434 CYASSL_MSG("\tfail: constraint not BOOLEAN");
ashleymills 0:714293de3836 2435 return;
ashleymills 0:714293de3836 2436 }
ashleymills 0:714293de3836 2437
ashleymills 0:714293de3836 2438 if (GetLength(input, &idx, &length, sz) < 0)
ashleymills 0:714293de3836 2439 {
ashleymills 0:714293de3836 2440 CYASSL_MSG("\tfail: length");
ashleymills 0:714293de3836 2441 return;
ashleymills 0:714293de3836 2442 }
ashleymills 0:714293de3836 2443
ashleymills 0:714293de3836 2444 if (input[idx])
ashleymills 0:714293de3836 2445 cert->isCA = 1;
ashleymills 0:714293de3836 2446 }
ashleymills 0:714293de3836 2447
ashleymills 0:714293de3836 2448
ashleymills 0:714293de3836 2449 #define CRLDP_FULL_NAME 0
ashleymills 0:714293de3836 2450 /* From RFC3280 SS4.2.1.14, Distribution Point Name*/
ashleymills 0:714293de3836 2451 #define GENERALNAME_URI 6
ashleymills 0:714293de3836 2452 /* From RFC3280 SS4.2.1.7, GeneralName */
ashleymills 0:714293de3836 2453
ashleymills 0:714293de3836 2454 static void DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
ashleymills 0:714293de3836 2455 {
ashleymills 0:714293de3836 2456 word32 idx = 0;
ashleymills 0:714293de3836 2457 int length = 0;
ashleymills 0:714293de3836 2458
ashleymills 0:714293de3836 2459 CYASSL_ENTER("DecodeCrlDist");
ashleymills 0:714293de3836 2460
ashleymills 0:714293de3836 2461 /* Unwrap the list of Distribution Points*/
ashleymills 0:714293de3836 2462 if (GetSequence(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2463
ashleymills 0:714293de3836 2464 /* Unwrap a single Distribution Point */
ashleymills 0:714293de3836 2465 if (GetSequence(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2466
ashleymills 0:714293de3836 2467 /* The Distribution Point has three explicit optional members
ashleymills 0:714293de3836 2468 * First check for a DistributionPointName
ashleymills 0:714293de3836 2469 */
ashleymills 0:714293de3836 2470 if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
ashleymills 0:714293de3836 2471 {
ashleymills 0:714293de3836 2472 idx++;
ashleymills 0:714293de3836 2473 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2474
ashleymills 0:714293de3836 2475 if (input[idx] ==
ashleymills 0:714293de3836 2476 (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME))
ashleymills 0:714293de3836 2477 {
ashleymills 0:714293de3836 2478 idx++;
ashleymills 0:714293de3836 2479 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2480
ashleymills 0:714293de3836 2481 if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
ashleymills 0:714293de3836 2482 {
ashleymills 0:714293de3836 2483 idx++;
ashleymills 0:714293de3836 2484 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2485
ashleymills 0:714293de3836 2486 cert->extCrlInfoSz = length;
ashleymills 0:714293de3836 2487 cert->extCrlInfo = input + idx;
ashleymills 0:714293de3836 2488 idx += length;
ashleymills 0:714293de3836 2489 }
ashleymills 0:714293de3836 2490 else
ashleymills 0:714293de3836 2491 /* This isn't a URI, skip it. */
ashleymills 0:714293de3836 2492 idx += length;
ashleymills 0:714293de3836 2493 }
ashleymills 0:714293de3836 2494 else
ashleymills 0:714293de3836 2495 /* This isn't a FULLNAME, skip it. */
ashleymills 0:714293de3836 2496 idx += length;
ashleymills 0:714293de3836 2497 }
ashleymills 0:714293de3836 2498
ashleymills 0:714293de3836 2499 /* Check for reasonFlags */
ashleymills 0:714293de3836 2500 if (idx < (word32)sz &&
ashleymills 0:714293de3836 2501 input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
ashleymills 0:714293de3836 2502 {
ashleymills 0:714293de3836 2503 idx++;
ashleymills 0:714293de3836 2504 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2505 idx += length;
ashleymills 0:714293de3836 2506 }
ashleymills 0:714293de3836 2507
ashleymills 0:714293de3836 2508 /* Check for cRLIssuer */
ashleymills 0:714293de3836 2509 if (idx < (word32)sz &&
ashleymills 0:714293de3836 2510 input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
ashleymills 0:714293de3836 2511 {
ashleymills 0:714293de3836 2512 idx++;
ashleymills 0:714293de3836 2513 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2514 idx += length;
ashleymills 0:714293de3836 2515 }
ashleymills 0:714293de3836 2516
ashleymills 0:714293de3836 2517 if (idx < (word32)sz)
ashleymills 0:714293de3836 2518 {
ashleymills 0:714293de3836 2519 CYASSL_MSG("\tThere are more CRL Distribution Point records, "
ashleymills 0:714293de3836 2520 "but we only use the first one.");
ashleymills 0:714293de3836 2521 }
ashleymills 0:714293de3836 2522
ashleymills 0:714293de3836 2523 return;
ashleymills 0:714293de3836 2524 }
ashleymills 0:714293de3836 2525
ashleymills 0:714293de3836 2526
ashleymills 0:714293de3836 2527 static void DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
ashleymills 0:714293de3836 2528 /*
ashleymills 0:714293de3836 2529 * Read the first of the Authority Information Access records. If there are
ashleymills 0:714293de3836 2530 * any issues, return without saving the record.
ashleymills 0:714293de3836 2531 */
ashleymills 0:714293de3836 2532 {
ashleymills 0:714293de3836 2533 word32 idx = 0;
ashleymills 0:714293de3836 2534 int length = 0;
ashleymills 0:714293de3836 2535 word32 oid;
ashleymills 0:714293de3836 2536
ashleymills 0:714293de3836 2537 /* Unwrap the list of AIAs */
ashleymills 0:714293de3836 2538 if (GetSequence(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2539
ashleymills 0:714293de3836 2540 /* Unwrap a single AIA */
ashleymills 0:714293de3836 2541 if (GetSequence(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2542
ashleymills 0:714293de3836 2543 oid = 0;
ashleymills 0:714293de3836 2544 if (GetObjectId(input, &idx, &oid, sz) < 0) return;
ashleymills 0:714293de3836 2545
ashleymills 0:714293de3836 2546 /* Only supporting URIs right now. */
ashleymills 0:714293de3836 2547 if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
ashleymills 0:714293de3836 2548 {
ashleymills 0:714293de3836 2549 idx++;
ashleymills 0:714293de3836 2550 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2551
ashleymills 0:714293de3836 2552 cert->extAuthInfoSz = length;
ashleymills 0:714293de3836 2553 cert->extAuthInfo = input + idx;
ashleymills 0:714293de3836 2554 idx += length;
ashleymills 0:714293de3836 2555 }
ashleymills 0:714293de3836 2556 else
ashleymills 0:714293de3836 2557 {
ashleymills 0:714293de3836 2558 /* Skip anything else. */
ashleymills 0:714293de3836 2559 idx++;
ashleymills 0:714293de3836 2560 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2561 idx += length;
ashleymills 0:714293de3836 2562 }
ashleymills 0:714293de3836 2563
ashleymills 0:714293de3836 2564 if (idx < (word32)sz)
ashleymills 0:714293de3836 2565 {
ashleymills 0:714293de3836 2566 CYASSL_MSG("\tThere are more Authority Information Access records, "
ashleymills 0:714293de3836 2567 "but we only use first one.");
ashleymills 0:714293de3836 2568 }
ashleymills 0:714293de3836 2569
ashleymills 0:714293de3836 2570 return;
ashleymills 0:714293de3836 2571 }
ashleymills 0:714293de3836 2572
ashleymills 0:714293de3836 2573
ashleymills 0:714293de3836 2574 static void DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
ashleymills 0:714293de3836 2575 {
ashleymills 0:714293de3836 2576 word32 idx = 0;
ashleymills 0:714293de3836 2577 int length = 0;
ashleymills 0:714293de3836 2578
ashleymills 0:714293de3836 2579 CYASSL_ENTER("DecodeAuthKeyId");
ashleymills 0:714293de3836 2580
ashleymills 0:714293de3836 2581 if (GetSequence(input, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 2582 CYASSL_MSG("\tfail: should be a SEQUENCE\n");
ashleymills 0:714293de3836 2583 return;
ashleymills 0:714293de3836 2584 }
ashleymills 0:714293de3836 2585
ashleymills 0:714293de3836 2586 if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
ashleymills 0:714293de3836 2587 CYASSL_MSG("\tfail: wanted OPTIONAL item 0, not available\n");
ashleymills 0:714293de3836 2588 }
ashleymills 0:714293de3836 2589
ashleymills 0:714293de3836 2590 if (GetLength(input, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 2591 CYASSL_MSG("\tfail: extension data length");
ashleymills 0:714293de3836 2592 return;
ashleymills 0:714293de3836 2593 }
ashleymills 0:714293de3836 2594
ashleymills 0:714293de3836 2595 if (length == SHA_SIZE) {
ashleymills 0:714293de3836 2596 XMEMCPY(cert->extAuthKeyId, input + idx, length);
ashleymills 0:714293de3836 2597 }
ashleymills 0:714293de3836 2598 else {
ashleymills 0:714293de3836 2599 Sha sha;
ashleymills 0:714293de3836 2600 InitSha(&sha);
ashleymills 0:714293de3836 2601 ShaUpdate(&sha, input + idx, length);
ashleymills 0:714293de3836 2602 ShaFinal(&sha, cert->extAuthKeyId);
ashleymills 0:714293de3836 2603 }
ashleymills 0:714293de3836 2604 cert->extAuthKeyIdSet = 1;
ashleymills 0:714293de3836 2605
ashleymills 0:714293de3836 2606 return;
ashleymills 0:714293de3836 2607 }
ashleymills 0:714293de3836 2608
ashleymills 0:714293de3836 2609
ashleymills 0:714293de3836 2610 static void DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert)
ashleymills 0:714293de3836 2611 {
ashleymills 0:714293de3836 2612 word32 idx = 0;
ashleymills 0:714293de3836 2613 int length = 0;
ashleymills 0:714293de3836 2614
ashleymills 0:714293de3836 2615 CYASSL_ENTER("DecodeSubjKeyId");
ashleymills 0:714293de3836 2616
ashleymills 0:714293de3836 2617 if (input[idx++] != ASN_OCTET_STRING) {
ashleymills 0:714293de3836 2618 CYASSL_MSG("\tfail: should be an OCTET STRING");
ashleymills 0:714293de3836 2619 return;
ashleymills 0:714293de3836 2620 }
ashleymills 0:714293de3836 2621
ashleymills 0:714293de3836 2622 if (GetLength(input, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 2623 CYASSL_MSG("\tfail: extension data length");
ashleymills 0:714293de3836 2624 return;
ashleymills 0:714293de3836 2625 }
ashleymills 0:714293de3836 2626
ashleymills 0:714293de3836 2627 if (length == SIGNER_DIGEST_SIZE) {
ashleymills 0:714293de3836 2628 XMEMCPY(cert->extSubjKeyId, input + idx, length);
ashleymills 0:714293de3836 2629 }
ashleymills 0:714293de3836 2630 else {
ashleymills 0:714293de3836 2631 Sha sha;
ashleymills 0:714293de3836 2632 InitSha(&sha);
ashleymills 0:714293de3836 2633 ShaUpdate(&sha, input + idx, length);
ashleymills 0:714293de3836 2634 ShaFinal(&sha, cert->extSubjKeyId);
ashleymills 0:714293de3836 2635 }
ashleymills 0:714293de3836 2636 cert->extSubjKeyIdSet = 1;
ashleymills 0:714293de3836 2637
ashleymills 0:714293de3836 2638 return;
ashleymills 0:714293de3836 2639 }
ashleymills 0:714293de3836 2640
ashleymills 0:714293de3836 2641
ashleymills 0:714293de3836 2642 static void DecodeCertExtensions(DecodedCert* cert)
ashleymills 0:714293de3836 2643 /*
ashleymills 0:714293de3836 2644 * Processing the Certificate Extensions. This does not modify the current
ashleymills 0:714293de3836 2645 * index. It is works starting with the recorded extensions pointer.
ashleymills 0:714293de3836 2646 */
ashleymills 0:714293de3836 2647 {
ashleymills 0:714293de3836 2648 word32 idx = 0;
ashleymills 0:714293de3836 2649 int sz = cert->extensionsSz;
ashleymills 0:714293de3836 2650 byte* input = cert->extensions;
ashleymills 0:714293de3836 2651 int length;
ashleymills 0:714293de3836 2652 word32 oid;
ashleymills 0:714293de3836 2653
ashleymills 0:714293de3836 2654 CYASSL_ENTER("DecodeCertExtensions");
ashleymills 0:714293de3836 2655
ashleymills 0:714293de3836 2656 if (input == NULL || sz == 0) return;
ashleymills 0:714293de3836 2657
ashleymills 0:714293de3836 2658 if (input[idx++] != ASN_EXTENSIONS) return;
ashleymills 0:714293de3836 2659
ashleymills 0:714293de3836 2660 if (GetLength(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2661
ashleymills 0:714293de3836 2662 if (GetSequence(input, &idx, &length, sz) < 0) return;
ashleymills 0:714293de3836 2663
ashleymills 0:714293de3836 2664 while (idx < (word32)sz) {
ashleymills 0:714293de3836 2665 if (GetSequence(input, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 2666 CYASSL_MSG("\tfail: should be a SEQUENCE");
ashleymills 0:714293de3836 2667 return;
ashleymills 0:714293de3836 2668 }
ashleymills 0:714293de3836 2669
ashleymills 0:714293de3836 2670 oid = 0;
ashleymills 0:714293de3836 2671 if (GetObjectId(input, &idx, &oid, sz) < 0) {
ashleymills 0:714293de3836 2672 CYASSL_MSG("\tfail: OBJECT ID");
ashleymills 0:714293de3836 2673 return;
ashleymills 0:714293de3836 2674 }
ashleymills 0:714293de3836 2675
ashleymills 0:714293de3836 2676 /* check for critical flag */
ashleymills 0:714293de3836 2677 if (input[idx] == ASN_BOOLEAN) {
ashleymills 0:714293de3836 2678 CYASSL_MSG("\tfound optional critical flag, moving past");
ashleymills 0:714293de3836 2679 idx += (ASN_BOOL_SIZE + 1);
ashleymills 0:714293de3836 2680 }
ashleymills 0:714293de3836 2681
ashleymills 0:714293de3836 2682 /* process the extension based on the OID */
ashleymills 0:714293de3836 2683 if (input[idx++] != ASN_OCTET_STRING) {
ashleymills 0:714293de3836 2684 CYASSL_MSG("\tfail: should be an OCTET STRING");
ashleymills 0:714293de3836 2685 return;
ashleymills 0:714293de3836 2686 }
ashleymills 0:714293de3836 2687
ashleymills 0:714293de3836 2688 if (GetLength(input, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 2689 CYASSL_MSG("\tfail: extension data length");
ashleymills 0:714293de3836 2690 return;
ashleymills 0:714293de3836 2691 }
ashleymills 0:714293de3836 2692
ashleymills 0:714293de3836 2693 switch (oid) {
ashleymills 0:714293de3836 2694 case BASIC_CA_OID:
ashleymills 0:714293de3836 2695 DecodeBasicCaConstraint(&input[idx], length, cert);
ashleymills 0:714293de3836 2696 break;
ashleymills 0:714293de3836 2697
ashleymills 0:714293de3836 2698 case CRL_DIST_OID:
ashleymills 0:714293de3836 2699 DecodeCrlDist(&input[idx], length, cert);
ashleymills 0:714293de3836 2700 break;
ashleymills 0:714293de3836 2701
ashleymills 0:714293de3836 2702 case AUTH_INFO_OID:
ashleymills 0:714293de3836 2703 DecodeAuthInfo(&input[idx], length, cert);
ashleymills 0:714293de3836 2704 break;
ashleymills 0:714293de3836 2705
ashleymills 0:714293de3836 2706 case ALT_NAMES_OID:
ashleymills 0:714293de3836 2707 DecodeAltNames(&input[idx], length, cert);
ashleymills 0:714293de3836 2708
ashleymills 0:714293de3836 2709 case AUTH_KEY_OID:
ashleymills 0:714293de3836 2710 DecodeAuthKeyId(&input[idx], length, cert);
ashleymills 0:714293de3836 2711 break;
ashleymills 0:714293de3836 2712
ashleymills 0:714293de3836 2713 case SUBJ_KEY_OID:
ashleymills 0:714293de3836 2714 DecodeSubjKeyId(&input[idx], length, cert);
ashleymills 0:714293de3836 2715 break;
ashleymills 0:714293de3836 2716
ashleymills 0:714293de3836 2717 default:
ashleymills 0:714293de3836 2718 CYASSL_MSG("\tExtension type not handled, skipping");
ashleymills 0:714293de3836 2719 break;
ashleymills 0:714293de3836 2720 }
ashleymills 0:714293de3836 2721 idx += length;
ashleymills 0:714293de3836 2722 }
ashleymills 0:714293de3836 2723
ashleymills 0:714293de3836 2724 return;
ashleymills 0:714293de3836 2725 }
ashleymills 0:714293de3836 2726
ashleymills 0:714293de3836 2727
ashleymills 0:714293de3836 2728 int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
ashleymills 0:714293de3836 2729 {
ashleymills 0:714293de3836 2730 int ret;
ashleymills 0:714293de3836 2731 char* ptr;
ashleymills 0:714293de3836 2732
ashleymills 0:714293de3836 2733 ret = ParseCertRelative(cert, type, verify, cm);
ashleymills 0:714293de3836 2734 if (ret < 0)
ashleymills 0:714293de3836 2735 return ret;
ashleymills 0:714293de3836 2736
ashleymills 0:714293de3836 2737 if (cert->subjectCNLen > 0) {
ashleymills 0:714293de3836 2738 ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap,
ashleymills 0:714293de3836 2739 DYNAMIC_TYPE_SUBJECT_CN);
ashleymills 0:714293de3836 2740 if (ptr == NULL)
ashleymills 0:714293de3836 2741 return MEMORY_E;
ashleymills 0:714293de3836 2742 XMEMCPY(ptr, cert->subjectCN, cert->subjectCNLen);
ashleymills 0:714293de3836 2743 ptr[cert->subjectCNLen] = '\0';
ashleymills 0:714293de3836 2744 cert->subjectCN = ptr;
ashleymills 0:714293de3836 2745 cert->subjectCNStored = 1;
ashleymills 0:714293de3836 2746 }
ashleymills 0:714293de3836 2747
ashleymills 0:714293de3836 2748 if (cert->keyOID == RSAk && cert->pubKeySize > 0) {
ashleymills 0:714293de3836 2749 ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap,
ashleymills 0:714293de3836 2750 DYNAMIC_TYPE_PUBLIC_KEY);
ashleymills 0:714293de3836 2751 if (ptr == NULL)
ashleymills 0:714293de3836 2752 return MEMORY_E;
ashleymills 0:714293de3836 2753 XMEMCPY(ptr, cert->publicKey, cert->pubKeySize);
ashleymills 0:714293de3836 2754 cert->publicKey = (byte *)ptr;
ashleymills 0:714293de3836 2755 cert->pubKeyStored = 1;
ashleymills 0:714293de3836 2756 }
ashleymills 0:714293de3836 2757
ashleymills 0:714293de3836 2758 return ret;
ashleymills 0:714293de3836 2759 }
ashleymills 0:714293de3836 2760
ashleymills 0:714293de3836 2761
ashleymills 0:714293de3836 2762 /* from SSL proper, for locking can't do find here anymore */
ashleymills 0:714293de3836 2763 #ifdef __cplusplus
ashleymills 0:714293de3836 2764 extern "C" {
ashleymills 0:714293de3836 2765 #endif
ashleymills 0:714293de3836 2766 CYASSL_LOCAL Signer* GetCA(void* signers, byte* hash);
ashleymills 0:714293de3836 2767 #ifndef NO_SKID
ashleymills 0:714293de3836 2768 CYASSL_LOCAL Signer* GetCAByName(void* signers, byte* hash);
ashleymills 0:714293de3836 2769 #endif
ashleymills 0:714293de3836 2770 #ifdef __cplusplus
ashleymills 0:714293de3836 2771 }
ashleymills 0:714293de3836 2772 #endif
ashleymills 0:714293de3836 2773
ashleymills 0:714293de3836 2774
ashleymills 0:714293de3836 2775 int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
ashleymills 0:714293de3836 2776 {
ashleymills 0:714293de3836 2777 word32 confirmOID;
ashleymills 0:714293de3836 2778 int ret;
ashleymills 0:714293de3836 2779 int badDate = 0;
ashleymills 0:714293de3836 2780
ashleymills 0:714293de3836 2781 if ((ret = DecodeToKey(cert, verify)) < 0) {
ashleymills 0:714293de3836 2782 if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
ashleymills 0:714293de3836 2783 badDate = ret;
ashleymills 0:714293de3836 2784 else
ashleymills 0:714293de3836 2785 return ret;
ashleymills 0:714293de3836 2786 }
ashleymills 0:714293de3836 2787
ashleymills 0:714293de3836 2788 if (cert->srcIdx != cert->sigIndex) {
ashleymills 0:714293de3836 2789 if (cert->srcIdx < cert->sigIndex) {
ashleymills 0:714293de3836 2790 /* save extensions */
ashleymills 0:714293de3836 2791 cert->extensions = &cert->source[cert->srcIdx];
ashleymills 0:714293de3836 2792 cert->extensionsSz = cert->sigIndex - cert->srcIdx;
ashleymills 0:714293de3836 2793 cert->extensionsIdx = cert->srcIdx; /* for potential later use */
ashleymills 0:714293de3836 2794 }
ashleymills 0:714293de3836 2795 DecodeCertExtensions(cert);
ashleymills 0:714293de3836 2796 /* advance past extensions */
ashleymills 0:714293de3836 2797 cert->srcIdx = cert->sigIndex;
ashleymills 0:714293de3836 2798 }
ashleymills 0:714293de3836 2799
ashleymills 0:714293de3836 2800 if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
ashleymills 0:714293de3836 2801 cert->maxIdx)) < 0)
ashleymills 0:714293de3836 2802 return ret;
ashleymills 0:714293de3836 2803
ashleymills 0:714293de3836 2804 if ((ret = GetSignature(cert)) < 0)
ashleymills 0:714293de3836 2805 return ret;
ashleymills 0:714293de3836 2806
ashleymills 0:714293de3836 2807 if (confirmOID != cert->signatureOID)
ashleymills 0:714293de3836 2808 return ASN_SIG_OID_E;
ashleymills 0:714293de3836 2809
ashleymills 0:714293de3836 2810 #ifndef NO_SKID
ashleymills 0:714293de3836 2811 if (cert->extSubjKeyIdSet == 0) {
ashleymills 0:714293de3836 2812 Sha sha;
ashleymills 0:714293de3836 2813 InitSha(&sha);
ashleymills 0:714293de3836 2814 ShaUpdate(&sha, cert->publicKey, cert->pubKeySize);
ashleymills 0:714293de3836 2815 ShaFinal(&sha, cert->extSubjKeyId);
ashleymills 0:714293de3836 2816 cert->extSubjKeyIdSet = 1;
ashleymills 0:714293de3836 2817 }
ashleymills 0:714293de3836 2818 #endif
ashleymills 0:714293de3836 2819
ashleymills 0:714293de3836 2820 if (verify && type != CA_TYPE) {
ashleymills 0:714293de3836 2821 Signer* ca = NULL;
ashleymills 0:714293de3836 2822 #ifndef NO_SKID
ashleymills 0:714293de3836 2823 if (cert->extAuthKeyIdSet)
ashleymills 0:714293de3836 2824 ca = GetCA(cm, cert->extAuthKeyId);
ashleymills 0:714293de3836 2825 if (ca == NULL)
ashleymills 0:714293de3836 2826 ca = GetCAByName(cm, cert->issuerHash);
ashleymills 0:714293de3836 2827 #else /* NO_SKID */
ashleymills 0:714293de3836 2828 ca = GetCA(cm, cert->issuerHash);
ashleymills 0:714293de3836 2829 #endif /* NO SKID */
ashleymills 0:714293de3836 2830 CYASSL_MSG("About to verify certificate signature");
ashleymills 0:714293de3836 2831
ashleymills 0:714293de3836 2832 if (ca) {
ashleymills 0:714293de3836 2833 #ifdef HAVE_OCSP
ashleymills 0:714293de3836 2834 /* Need the ca's public key hash for OCSP */
ashleymills 0:714293de3836 2835 {
ashleymills 0:714293de3836 2836 Sha sha;
ashleymills 0:714293de3836 2837 InitSha(&sha);
ashleymills 0:714293de3836 2838 ShaUpdate(&sha, ca->publicKey, ca->pubKeySize);
ashleymills 0:714293de3836 2839 ShaFinal(&sha, cert->issuerKeyHash);
ashleymills 0:714293de3836 2840 }
ashleymills 0:714293de3836 2841 #endif /* HAVE_OCSP */
ashleymills 0:714293de3836 2842 /* try to confirm/verify signature */
ashleymills 0:714293de3836 2843 if (!ConfirmSignature(cert->source + cert->certBegin,
ashleymills 0:714293de3836 2844 cert->sigIndex - cert->certBegin,
ashleymills 0:714293de3836 2845 ca->publicKey, ca->pubKeySize, ca->keyOID,
ashleymills 0:714293de3836 2846 cert->signature, cert->sigLength, cert->signatureOID,
ashleymills 0:714293de3836 2847 cert->heap)) {
ashleymills 0:714293de3836 2848 CYASSL_MSG("Confirm signature failed");
ashleymills 0:714293de3836 2849 return ASN_SIG_CONFIRM_E;
ashleymills 0:714293de3836 2850 }
ashleymills 0:714293de3836 2851 }
ashleymills 0:714293de3836 2852 else {
ashleymills 0:714293de3836 2853 /* no signer */
ashleymills 0:714293de3836 2854 CYASSL_MSG("No CA signer to verify with");
ashleymills 0:714293de3836 2855 return ASN_NO_SIGNER_E;
ashleymills 0:714293de3836 2856 }
ashleymills 0:714293de3836 2857 }
ashleymills 0:714293de3836 2858
ashleymills 0:714293de3836 2859 if (badDate != 0)
ashleymills 0:714293de3836 2860 return badDate;
ashleymills 0:714293de3836 2861
ashleymills 0:714293de3836 2862 return 0;
ashleymills 0:714293de3836 2863 }
ashleymills 0:714293de3836 2864
ashleymills 0:714293de3836 2865
ashleymills 0:714293de3836 2866 /* Create and init an new signer */
ashleymills 0:714293de3836 2867 Signer* MakeSigner(void* heap)
ashleymills 0:714293de3836 2868 {
ashleymills 0:714293de3836 2869 Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap,
ashleymills 0:714293de3836 2870 DYNAMIC_TYPE_SIGNER);
ashleymills 0:714293de3836 2871 if (signer) {
ashleymills 0:714293de3836 2872 signer->pubKeySize = 0;
ashleymills 0:714293de3836 2873 signer->keyOID = 0;
ashleymills 0:714293de3836 2874 signer->publicKey = NULL;
ashleymills 0:714293de3836 2875 signer->nameLen = 0;
ashleymills 0:714293de3836 2876 signer->name = NULL;
ashleymills 0:714293de3836 2877 signer->next = NULL;
ashleymills 0:714293de3836 2878 }
ashleymills 0:714293de3836 2879 (void)heap;
ashleymills 0:714293de3836 2880
ashleymills 0:714293de3836 2881 return signer;
ashleymills 0:714293de3836 2882 }
ashleymills 0:714293de3836 2883
ashleymills 0:714293de3836 2884
ashleymills 0:714293de3836 2885 /* Free an individual signer */
ashleymills 0:714293de3836 2886 void FreeSigner(Signer* signer, void* heap)
ashleymills 0:714293de3836 2887 {
ashleymills 0:714293de3836 2888 XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
ashleymills 0:714293de3836 2889 XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
ashleymills 0:714293de3836 2890 XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
ashleymills 0:714293de3836 2891
ashleymills 0:714293de3836 2892 (void)heap;
ashleymills 0:714293de3836 2893 }
ashleymills 0:714293de3836 2894
ashleymills 0:714293de3836 2895
ashleymills 0:714293de3836 2896 /* Free the whole singer table with number of rows */
ashleymills 0:714293de3836 2897 void FreeSignerTable(Signer** table, int rows, void* heap)
ashleymills 0:714293de3836 2898 {
ashleymills 0:714293de3836 2899 int i;
ashleymills 0:714293de3836 2900
ashleymills 0:714293de3836 2901 for (i = 0; i < rows; i++) {
ashleymills 0:714293de3836 2902 Signer* signer = table[i];
ashleymills 0:714293de3836 2903 while (signer) {
ashleymills 0:714293de3836 2904 Signer* next = signer->next;
ashleymills 0:714293de3836 2905 FreeSigner(signer, heap);
ashleymills 0:714293de3836 2906 signer = next;
ashleymills 0:714293de3836 2907 }
ashleymills 0:714293de3836 2908 table[i] = NULL;
ashleymills 0:714293de3836 2909 }
ashleymills 0:714293de3836 2910 }
ashleymills 0:714293de3836 2911
ashleymills 0:714293de3836 2912
ashleymills 0:714293de3836 2913 #if defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN)
ashleymills 0:714293de3836 2914
ashleymills 0:714293de3836 2915 static int SetMyVersion(word32 version, byte* output, int header)
ashleymills 0:714293de3836 2916 {
ashleymills 0:714293de3836 2917 int i = 0;
ashleymills 0:714293de3836 2918
ashleymills 0:714293de3836 2919 if (header) {
ashleymills 0:714293de3836 2920 output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
ashleymills 0:714293de3836 2921 output[i++] = ASN_BIT_STRING;
ashleymills 0:714293de3836 2922 }
ashleymills 0:714293de3836 2923 output[i++] = ASN_INTEGER;
ashleymills 0:714293de3836 2924 output[i++] = 0x01;
ashleymills 0:714293de3836 2925 output[i++] = (byte)version;
ashleymills 0:714293de3836 2926
ashleymills 0:714293de3836 2927 return i;
ashleymills 0:714293de3836 2928 }
ashleymills 0:714293de3836 2929
ashleymills 0:714293de3836 2930
ashleymills 0:714293de3836 2931 int DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
ashleymills 0:714293de3836 2932 int type)
ashleymills 0:714293de3836 2933 {
ashleymills 0:714293de3836 2934 char header[80];
ashleymills 0:714293de3836 2935 char footer[80];
ashleymills 0:714293de3836 2936
ashleymills 0:714293de3836 2937 int headerLen;
ashleymills 0:714293de3836 2938 int footerLen;
ashleymills 0:714293de3836 2939 int i;
ashleymills 0:714293de3836 2940 int err;
ashleymills 0:714293de3836 2941 int outLen; /* return length or error */
ashleymills 0:714293de3836 2942
ashleymills 0:714293de3836 2943 if (type == CERT_TYPE) {
ashleymills 0:714293de3836 2944 XSTRNCPY(header, "-----BEGIN CERTIFICATE-----\n", sizeof(header));
ashleymills 0:714293de3836 2945 XSTRNCPY(footer, "-----END CERTIFICATE-----\n", sizeof(footer));
ashleymills 0:714293de3836 2946 }
ashleymills 0:714293de3836 2947 else if (type == PRIVATEKEY_TYPE) {
ashleymills 0:714293de3836 2948 XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----\n", sizeof(header));
ashleymills 0:714293de3836 2949 XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----\n", sizeof(footer));
ashleymills 0:714293de3836 2950 }
ashleymills 0:714293de3836 2951 #ifdef HAVE_ECC
ashleymills 0:714293de3836 2952 else if (type == ECC_PRIVATEKEY_TYPE) {
ashleymills 0:714293de3836 2953 XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----\n", sizeof(header));
ashleymills 0:714293de3836 2954 XSTRNCPY(footer, "-----END EC PRIVATE KEY-----\n", sizeof(footer));
ashleymills 0:714293de3836 2955 }
ashleymills 0:714293de3836 2956 #endif
ashleymills 0:714293de3836 2957 else
ashleymills 0:714293de3836 2958 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 2959
ashleymills 0:714293de3836 2960 headerLen = (int)XSTRLEN(header);
ashleymills 0:714293de3836 2961 footerLen = (int)XSTRLEN(footer);
ashleymills 0:714293de3836 2962
ashleymills 0:714293de3836 2963 if (!der || !output)
ashleymills 0:714293de3836 2964 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 2965
ashleymills 0:714293de3836 2966 /* don't even try if outSz too short */
ashleymills 0:714293de3836 2967 if (outSz < headerLen + footerLen + derSz)
ashleymills 0:714293de3836 2968 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 2969
ashleymills 0:714293de3836 2970 /* header */
ashleymills 0:714293de3836 2971 XMEMCPY(output, header, headerLen);
ashleymills 0:714293de3836 2972 i = headerLen;
ashleymills 0:714293de3836 2973
ashleymills 0:714293de3836 2974 /* body */
ashleymills 0:714293de3836 2975 outLen = outSz - (headerLen + footerLen); /* input to Base64_Encode */
ashleymills 0:714293de3836 2976 if ( (err = Base64_Encode(der, derSz, output + i, (word32*)&outLen)) < 0)
ashleymills 0:714293de3836 2977 return err;
ashleymills 0:714293de3836 2978 i += outLen;
ashleymills 0:714293de3836 2979
ashleymills 0:714293de3836 2980 /* footer */
ashleymills 0:714293de3836 2981 if ( (i + footerLen) > (int)outSz)
ashleymills 0:714293de3836 2982 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 2983 XMEMCPY(output + i, footer, footerLen);
ashleymills 0:714293de3836 2984
ashleymills 0:714293de3836 2985 return outLen + headerLen + footerLen;
ashleymills 0:714293de3836 2986 }
ashleymills 0:714293de3836 2987
ashleymills 0:714293de3836 2988
ashleymills 0:714293de3836 2989 #endif /* CYASSL_KEY_GEN || CYASSL_CERT_GEN */
ashleymills 0:714293de3836 2990
ashleymills 0:714293de3836 2991
ashleymills 0:714293de3836 2992 #if defined(CYASSL_KEY_GEN) && !defined(NO_RSA)
ashleymills 0:714293de3836 2993
ashleymills 0:714293de3836 2994
ashleymills 0:714293de3836 2995 static mp_int* GetRsaInt(RsaKey* key, int idx)
ashleymills 0:714293de3836 2996 {
ashleymills 0:714293de3836 2997 if (idx == 0)
ashleymills 0:714293de3836 2998 return &key->n;
ashleymills 0:714293de3836 2999 if (idx == 1)
ashleymills 0:714293de3836 3000 return &key->e;
ashleymills 0:714293de3836 3001 if (idx == 2)
ashleymills 0:714293de3836 3002 return &key->d;
ashleymills 0:714293de3836 3003 if (idx == 3)
ashleymills 0:714293de3836 3004 return &key->p;
ashleymills 0:714293de3836 3005 if (idx == 4)
ashleymills 0:714293de3836 3006 return &key->q;
ashleymills 0:714293de3836 3007 if (idx == 5)
ashleymills 0:714293de3836 3008 return &key->dP;
ashleymills 0:714293de3836 3009 if (idx == 6)
ashleymills 0:714293de3836 3010 return &key->dQ;
ashleymills 0:714293de3836 3011 if (idx == 7)
ashleymills 0:714293de3836 3012 return &key->u;
ashleymills 0:714293de3836 3013
ashleymills 0:714293de3836 3014 return NULL;
ashleymills 0:714293de3836 3015 }
ashleymills 0:714293de3836 3016
ashleymills 0:714293de3836 3017
ashleymills 0:714293de3836 3018 /* Release Tmp RSA resources */
ashleymills 0:714293de3836 3019 static INLINE void FreeTmpRsas(byte** tmps, void* heap)
ashleymills 0:714293de3836 3020 {
ashleymills 0:714293de3836 3021 int i;
ashleymills 0:714293de3836 3022
ashleymills 0:714293de3836 3023 (void)heap;
ashleymills 0:714293de3836 3024
ashleymills 0:714293de3836 3025 for (i = 0; i < RSA_INTS; i++)
ashleymills 0:714293de3836 3026 XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA);
ashleymills 0:714293de3836 3027 }
ashleymills 0:714293de3836 3028
ashleymills 0:714293de3836 3029
ashleymills 0:714293de3836 3030 /* Convert RsaKey key to DER format, write to output (inLen), return bytes
ashleymills 0:714293de3836 3031 written */
ashleymills 0:714293de3836 3032 int RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
ashleymills 0:714293de3836 3033 {
ashleymills 0:714293de3836 3034 word32 seqSz, verSz, rawLen, intTotalLen = 0;
ashleymills 0:714293de3836 3035 word32 sizes[RSA_INTS];
ashleymills 0:714293de3836 3036 int i, j, outLen, ret = 0;
ashleymills 0:714293de3836 3037
ashleymills 0:714293de3836 3038 byte seq[MAX_SEQ_SZ];
ashleymills 0:714293de3836 3039 byte ver[MAX_VERSION_SZ];
ashleymills 0:714293de3836 3040 byte* tmps[RSA_INTS];
ashleymills 0:714293de3836 3041
ashleymills 0:714293de3836 3042 if (!key || !output)
ashleymills 0:714293de3836 3043 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 3044
ashleymills 0:714293de3836 3045 if (key->type != RSA_PRIVATE)
ashleymills 0:714293de3836 3046 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 3047
ashleymills 0:714293de3836 3048 for (i = 0; i < RSA_INTS; i++)
ashleymills 0:714293de3836 3049 tmps[i] = NULL;
ashleymills 0:714293de3836 3050
ashleymills 0:714293de3836 3051 /* write all big ints from key to DER tmps */
ashleymills 0:714293de3836 3052 for (i = 0; i < RSA_INTS; i++) {
ashleymills 0:714293de3836 3053 mp_int* keyInt = GetRsaInt(key, i);
ashleymills 0:714293de3836 3054 rawLen = mp_unsigned_bin_size(keyInt);
ashleymills 0:714293de3836 3055 tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
ashleymills 0:714293de3836 3056 DYNAMIC_TYPE_RSA);
ashleymills 0:714293de3836 3057 if (tmps[i] == NULL) {
ashleymills 0:714293de3836 3058 ret = MEMORY_E;
ashleymills 0:714293de3836 3059 break;
ashleymills 0:714293de3836 3060 }
ashleymills 0:714293de3836 3061
ashleymills 0:714293de3836 3062 tmps[i][0] = ASN_INTEGER;
ashleymills 0:714293de3836 3063 sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1; /* int tag */
ashleymills 0:714293de3836 3064
ashleymills 0:714293de3836 3065 if (sizes[i] <= MAX_SEQ_SZ) {
ashleymills 0:714293de3836 3066 int err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]);
ashleymills 0:714293de3836 3067 if (err == MP_OKAY) {
ashleymills 0:714293de3836 3068 sizes[i] += rawLen;
ashleymills 0:714293de3836 3069 intTotalLen += sizes[i];
ashleymills 0:714293de3836 3070 }
ashleymills 0:714293de3836 3071 else {
ashleymills 0:714293de3836 3072 ret = err;
ashleymills 0:714293de3836 3073 break;
ashleymills 0:714293de3836 3074 }
ashleymills 0:714293de3836 3075 }
ashleymills 0:714293de3836 3076 else {
ashleymills 0:714293de3836 3077 ret = ASN_INPUT_E;
ashleymills 0:714293de3836 3078 break;
ashleymills 0:714293de3836 3079 }
ashleymills 0:714293de3836 3080 }
ashleymills 0:714293de3836 3081
ashleymills 0:714293de3836 3082 if (ret != 0) {
ashleymills 0:714293de3836 3083 FreeTmpRsas(tmps, key->heap);
ashleymills 0:714293de3836 3084 return ret;
ashleymills 0:714293de3836 3085 }
ashleymills 0:714293de3836 3086
ashleymills 0:714293de3836 3087 /* make headers */
ashleymills 0:714293de3836 3088 verSz = SetMyVersion(0, ver, FALSE);
ashleymills 0:714293de3836 3089 seqSz = SetSequence(verSz + intTotalLen, seq);
ashleymills 0:714293de3836 3090
ashleymills 0:714293de3836 3091 outLen = seqSz + verSz + intTotalLen;
ashleymills 0:714293de3836 3092 if (outLen > (int)inLen)
ashleymills 0:714293de3836 3093 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 3094
ashleymills 0:714293de3836 3095 /* write to output */
ashleymills 0:714293de3836 3096 XMEMCPY(output, seq, seqSz);
ashleymills 0:714293de3836 3097 j = seqSz;
ashleymills 0:714293de3836 3098 XMEMCPY(output + j, ver, verSz);
ashleymills 0:714293de3836 3099 j += verSz;
ashleymills 0:714293de3836 3100
ashleymills 0:714293de3836 3101 for (i = 0; i < RSA_INTS; i++) {
ashleymills 0:714293de3836 3102 XMEMCPY(output + j, tmps[i], sizes[i]);
ashleymills 0:714293de3836 3103 j += sizes[i];
ashleymills 0:714293de3836 3104 }
ashleymills 0:714293de3836 3105 FreeTmpRsas(tmps, key->heap);
ashleymills 0:714293de3836 3106
ashleymills 0:714293de3836 3107 return outLen;
ashleymills 0:714293de3836 3108 }
ashleymills 0:714293de3836 3109
ashleymills 0:714293de3836 3110 #endif /* CYASSL_KEY_GEN && !NO_RSA */
ashleymills 0:714293de3836 3111
ashleymills 0:714293de3836 3112
ashleymills 0:714293de3836 3113 #if defined(CYASSL_CERT_GEN) && !defined(NO_RSA)
ashleymills 0:714293de3836 3114
ashleymills 0:714293de3836 3115
ashleymills 0:714293de3836 3116 #ifndef min
ashleymills 0:714293de3836 3117
ashleymills 0:714293de3836 3118 static INLINE word32 min(word32 a, word32 b)
ashleymills 0:714293de3836 3119 {
ashleymills 0:714293de3836 3120 return a > b ? b : a;
ashleymills 0:714293de3836 3121 }
ashleymills 0:714293de3836 3122
ashleymills 0:714293de3836 3123 #endif /* min */
ashleymills 0:714293de3836 3124
ashleymills 0:714293de3836 3125
ashleymills 0:714293de3836 3126 /* Initialize and Set Certficate defaults:
ashleymills 0:714293de3836 3127 version = 3 (0x2)
ashleymills 0:714293de3836 3128 serial = 0
ashleymills 0:714293de3836 3129 sigType = SHA_WITH_RSA
ashleymills 0:714293de3836 3130 issuer = blank
ashleymills 0:714293de3836 3131 daysValid = 500
ashleymills 0:714293de3836 3132 selfSigned = 1 (true) use subject as issuer
ashleymills 0:714293de3836 3133 subject = blank
ashleymills 0:714293de3836 3134 */
ashleymills 0:714293de3836 3135 void InitCert(Cert* cert)
ashleymills 0:714293de3836 3136 {
ashleymills 0:714293de3836 3137 cert->version = 2; /* version 3 is hex 2 */
ashleymills 0:714293de3836 3138 cert->sigType = CTC_SHAwRSA;
ashleymills 0:714293de3836 3139 cert->daysValid = 500;
ashleymills 0:714293de3836 3140 cert->selfSigned = 1;
ashleymills 0:714293de3836 3141 cert->isCA = 0;
ashleymills 0:714293de3836 3142 cert->bodySz = 0;
ashleymills 0:714293de3836 3143 #ifdef CYASSL_ALT_NAMES
ashleymills 0:714293de3836 3144 cert->altNamesSz = 0;
ashleymills 0:714293de3836 3145 cert->beforeDateSz = 0;
ashleymills 0:714293de3836 3146 cert->afterDateSz = 0;
ashleymills 0:714293de3836 3147 #endif
ashleymills 0:714293de3836 3148 cert->keyType = RSA_KEY;
ashleymills 0:714293de3836 3149 XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE);
ashleymills 0:714293de3836 3150
ashleymills 0:714293de3836 3151 cert->issuer.country[0] = '\0';
ashleymills 0:714293de3836 3152 cert->issuer.state[0] = '\0';
ashleymills 0:714293de3836 3153 cert->issuer.locality[0] = '\0';
ashleymills 0:714293de3836 3154 cert->issuer.sur[0] = '\0';
ashleymills 0:714293de3836 3155 cert->issuer.org[0] = '\0';
ashleymills 0:714293de3836 3156 cert->issuer.unit[0] = '\0';
ashleymills 0:714293de3836 3157 cert->issuer.commonName[0] = '\0';
ashleymills 0:714293de3836 3158 cert->issuer.email[0] = '\0';
ashleymills 0:714293de3836 3159
ashleymills 0:714293de3836 3160 cert->subject.country[0] = '\0';
ashleymills 0:714293de3836 3161 cert->subject.state[0] = '\0';
ashleymills 0:714293de3836 3162 cert->subject.locality[0] = '\0';
ashleymills 0:714293de3836 3163 cert->subject.sur[0] = '\0';
ashleymills 0:714293de3836 3164 cert->subject.org[0] = '\0';
ashleymills 0:714293de3836 3165 cert->subject.unit[0] = '\0';
ashleymills 0:714293de3836 3166 cert->subject.commonName[0] = '\0';
ashleymills 0:714293de3836 3167 cert->subject.email[0] = '\0';
ashleymills 0:714293de3836 3168 }
ashleymills 0:714293de3836 3169
ashleymills 0:714293de3836 3170
ashleymills 0:714293de3836 3171 /* DER encoded x509 Certificate */
ashleymills 0:714293de3836 3172 typedef struct DerCert {
ashleymills 0:714293de3836 3173 byte size[MAX_LENGTH_SZ]; /* length encoded */
ashleymills 0:714293de3836 3174 byte version[MAX_VERSION_SZ]; /* version encoded */
ashleymills 0:714293de3836 3175 byte serial[CTC_SERIAL_SIZE + MAX_LENGTH_SZ]; /* serial number encoded */
ashleymills 0:714293de3836 3176 byte sigAlgo[MAX_ALGO_SZ]; /* signature algo encoded */
ashleymills 0:714293de3836 3177 byte issuer[ASN_NAME_MAX]; /* issuer encoded */
ashleymills 0:714293de3836 3178 byte subject[ASN_NAME_MAX]; /* subject encoded */
ashleymills 0:714293de3836 3179 byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */
ashleymills 0:714293de3836 3180 byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */
ashleymills 0:714293de3836 3181 byte ca[MAX_CA_SZ]; /* basic constraint CA true size */
ashleymills 0:714293de3836 3182 byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */
ashleymills 0:714293de3836 3183 int sizeSz; /* encoded size length */
ashleymills 0:714293de3836 3184 int versionSz; /* encoded version length */
ashleymills 0:714293de3836 3185 int serialSz; /* encoded serial length */
ashleymills 0:714293de3836 3186 int sigAlgoSz; /* enocded sig alog length */
ashleymills 0:714293de3836 3187 int issuerSz; /* encoded issuer length */
ashleymills 0:714293de3836 3188 int subjectSz; /* encoded subject length */
ashleymills 0:714293de3836 3189 int validitySz; /* encoded validity length */
ashleymills 0:714293de3836 3190 int publicKeySz; /* encoded public key length */
ashleymills 0:714293de3836 3191 int caSz; /* encoded CA extension length */
ashleymills 0:714293de3836 3192 int extensionsSz; /* encoded extensions total length */
ashleymills 0:714293de3836 3193 int total; /* total encoded lengths */
ashleymills 0:714293de3836 3194 } DerCert;
ashleymills 0:714293de3836 3195
ashleymills 0:714293de3836 3196
ashleymills 0:714293de3836 3197 /* Write a set header to output */
ashleymills 0:714293de3836 3198 static word32 SetSet(word32 len, byte* output)
ashleymills 0:714293de3836 3199 {
ashleymills 0:714293de3836 3200 output[0] = ASN_SET | ASN_CONSTRUCTED;
ashleymills 0:714293de3836 3201 return SetLength(len, output + 1) + 1;
ashleymills 0:714293de3836 3202 }
ashleymills 0:714293de3836 3203
ashleymills 0:714293de3836 3204
ashleymills 0:714293de3836 3205 /* Write a serial number to output */
ashleymills 0:714293de3836 3206 static int SetSerial(const byte* serial, byte* output)
ashleymills 0:714293de3836 3207 {
ashleymills 0:714293de3836 3208 int length = 0;
ashleymills 0:714293de3836 3209
ashleymills 0:714293de3836 3210 output[length++] = ASN_INTEGER;
ashleymills 0:714293de3836 3211 length += SetLength(CTC_SERIAL_SIZE, &output[length]);
ashleymills 0:714293de3836 3212 XMEMCPY(&output[length], serial, CTC_SERIAL_SIZE);
ashleymills 0:714293de3836 3213
ashleymills 0:714293de3836 3214 return length + CTC_SERIAL_SIZE;
ashleymills 0:714293de3836 3215 }
ashleymills 0:714293de3836 3216
ashleymills 0:714293de3836 3217
ashleymills 0:714293de3836 3218 /* Write a public RSA key to output */
ashleymills 0:714293de3836 3219 static int SetPublicKey(byte* output, RsaKey* key)
ashleymills 0:714293de3836 3220 {
ashleymills 0:714293de3836 3221 byte n[MAX_RSA_INT_SZ];
ashleymills 0:714293de3836 3222 byte e[MAX_RSA_E_SZ];
ashleymills 0:714293de3836 3223 byte algo[MAX_ALGO_SZ];
ashleymills 0:714293de3836 3224 byte seq[MAX_SEQ_SZ];
ashleymills 0:714293de3836 3225 byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
ashleymills 0:714293de3836 3226 int nSz;
ashleymills 0:714293de3836 3227 int eSz;
ashleymills 0:714293de3836 3228 int algoSz;
ashleymills 0:714293de3836 3229 int seqSz;
ashleymills 0:714293de3836 3230 int lenSz;
ashleymills 0:714293de3836 3231 int idx;
ashleymills 0:714293de3836 3232 int rawLen;
ashleymills 0:714293de3836 3233
ashleymills 0:714293de3836 3234 /* n */
ashleymills 0:714293de3836 3235 rawLen = mp_unsigned_bin_size(&key->n);
ashleymills 0:714293de3836 3236 n[0] = ASN_INTEGER;
ashleymills 0:714293de3836 3237 nSz = SetLength(rawLen, n + 1) + 1; /* int tag */
ashleymills 0:714293de3836 3238
ashleymills 0:714293de3836 3239 if ( (nSz + rawLen) < (int)sizeof(n)) {
ashleymills 0:714293de3836 3240 int err = mp_to_unsigned_bin(&key->n, n + nSz);
ashleymills 0:714293de3836 3241 if (err == MP_OKAY)
ashleymills 0:714293de3836 3242 nSz += rawLen;
ashleymills 0:714293de3836 3243 else
ashleymills 0:714293de3836 3244 return MP_TO_E;
ashleymills 0:714293de3836 3245 }
ashleymills 0:714293de3836 3246 else
ashleymills 0:714293de3836 3247 return BUFFER_E;
ashleymills 0:714293de3836 3248
ashleymills 0:714293de3836 3249 /* e */
ashleymills 0:714293de3836 3250 rawLen = mp_unsigned_bin_size(&key->e);
ashleymills 0:714293de3836 3251 e[0] = ASN_INTEGER;
ashleymills 0:714293de3836 3252 eSz = SetLength(rawLen, e + 1) + 1; /* int tag */
ashleymills 0:714293de3836 3253
ashleymills 0:714293de3836 3254 if ( (eSz + rawLen) < (int)sizeof(e)) {
ashleymills 0:714293de3836 3255 int err = mp_to_unsigned_bin(&key->e, e + eSz);
ashleymills 0:714293de3836 3256 if (err == MP_OKAY)
ashleymills 0:714293de3836 3257 eSz += rawLen;
ashleymills 0:714293de3836 3258 else
ashleymills 0:714293de3836 3259 return MP_TO_E;
ashleymills 0:714293de3836 3260 }
ashleymills 0:714293de3836 3261 else
ashleymills 0:714293de3836 3262 return BUFFER_E;
ashleymills 0:714293de3836 3263
ashleymills 0:714293de3836 3264 /* headers */
ashleymills 0:714293de3836 3265 algoSz = SetAlgoID(RSAk, algo, keyType);
ashleymills 0:714293de3836 3266 seqSz = SetSequence(nSz + eSz, seq);
ashleymills 0:714293de3836 3267 lenSz = SetLength(seqSz + nSz + eSz + 1, len);
ashleymills 0:714293de3836 3268 len[lenSz++] = 0; /* trailing 0 */
ashleymills 0:714293de3836 3269
ashleymills 0:714293de3836 3270 /* write */
ashleymills 0:714293de3836 3271 idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output);
ashleymills 0:714293de3836 3272 /* 1 is for ASN_BIT_STRING */
ashleymills 0:714293de3836 3273 /* algo */
ashleymills 0:714293de3836 3274 XMEMCPY(output + idx, algo, algoSz);
ashleymills 0:714293de3836 3275 idx += algoSz;
ashleymills 0:714293de3836 3276 /* bit string */
ashleymills 0:714293de3836 3277 output[idx++] = ASN_BIT_STRING;
ashleymills 0:714293de3836 3278 /* length */
ashleymills 0:714293de3836 3279 XMEMCPY(output + idx, len, lenSz);
ashleymills 0:714293de3836 3280 idx += lenSz;
ashleymills 0:714293de3836 3281 /* seq */
ashleymills 0:714293de3836 3282 XMEMCPY(output + idx, seq, seqSz);
ashleymills 0:714293de3836 3283 idx += seqSz;
ashleymills 0:714293de3836 3284 /* n */
ashleymills 0:714293de3836 3285 XMEMCPY(output + idx, n, nSz);
ashleymills 0:714293de3836 3286 idx += nSz;
ashleymills 0:714293de3836 3287 /* e */
ashleymills 0:714293de3836 3288 XMEMCPY(output + idx, e, eSz);
ashleymills 0:714293de3836 3289 idx += eSz;
ashleymills 0:714293de3836 3290
ashleymills 0:714293de3836 3291 return idx;
ashleymills 0:714293de3836 3292 }
ashleymills 0:714293de3836 3293
ashleymills 0:714293de3836 3294
ashleymills 0:714293de3836 3295 static INLINE byte itob(int number)
ashleymills 0:714293de3836 3296 {
ashleymills 0:714293de3836 3297 return (byte)number + 0x30;
ashleymills 0:714293de3836 3298 }
ashleymills 0:714293de3836 3299
ashleymills 0:714293de3836 3300
ashleymills 0:714293de3836 3301 /* write time to output, format */
ashleymills 0:714293de3836 3302 static void SetTime(struct tm* date, byte* output)
ashleymills 0:714293de3836 3303 {
ashleymills 0:714293de3836 3304 int i = 0;
ashleymills 0:714293de3836 3305
ashleymills 0:714293de3836 3306 output[i++] = itob((date->tm_year % 10000) / 1000);
ashleymills 0:714293de3836 3307 output[i++] = itob((date->tm_year % 1000) / 100);
ashleymills 0:714293de3836 3308 output[i++] = itob((date->tm_year % 100) / 10);
ashleymills 0:714293de3836 3309 output[i++] = itob( date->tm_year % 10);
ashleymills 0:714293de3836 3310
ashleymills 0:714293de3836 3311 output[i++] = itob(date->tm_mon / 10);
ashleymills 0:714293de3836 3312 output[i++] = itob(date->tm_mon % 10);
ashleymills 0:714293de3836 3313
ashleymills 0:714293de3836 3314 output[i++] = itob(date->tm_mday / 10);
ashleymills 0:714293de3836 3315 output[i++] = itob(date->tm_mday % 10);
ashleymills 0:714293de3836 3316
ashleymills 0:714293de3836 3317 output[i++] = itob(date->tm_hour / 10);
ashleymills 0:714293de3836 3318 output[i++] = itob(date->tm_hour % 10);
ashleymills 0:714293de3836 3319
ashleymills 0:714293de3836 3320 output[i++] = itob(date->tm_min / 10);
ashleymills 0:714293de3836 3321 output[i++] = itob(date->tm_min % 10);
ashleymills 0:714293de3836 3322
ashleymills 0:714293de3836 3323 output[i++] = itob(date->tm_sec / 10);
ashleymills 0:714293de3836 3324 output[i++] = itob(date->tm_sec % 10);
ashleymills 0:714293de3836 3325
ashleymills 0:714293de3836 3326 output[i] = 'Z'; /* Zulu profile */
ashleymills 0:714293de3836 3327 }
ashleymills 0:714293de3836 3328
ashleymills 0:714293de3836 3329
ashleymills 0:714293de3836 3330 #ifdef CYASSL_ALT_NAMES
ashleymills 0:714293de3836 3331
ashleymills 0:714293de3836 3332 /* Copy Dates from cert, return bytes written */
ashleymills 0:714293de3836 3333 static int CopyValidity(byte* output, Cert* cert)
ashleymills 0:714293de3836 3334 {
ashleymills 0:714293de3836 3335 int seqSz;
ashleymills 0:714293de3836 3336
ashleymills 0:714293de3836 3337 CYASSL_ENTER("CopyValidity");
ashleymills 0:714293de3836 3338
ashleymills 0:714293de3836 3339 /* headers and output */
ashleymills 0:714293de3836 3340 seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output);
ashleymills 0:714293de3836 3341 XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
ashleymills 0:714293de3836 3342 XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
ashleymills 0:714293de3836 3343 cert->afterDateSz);
ashleymills 0:714293de3836 3344 return seqSz + cert->beforeDateSz + cert->afterDateSz;
ashleymills 0:714293de3836 3345 }
ashleymills 0:714293de3836 3346
ashleymills 0:714293de3836 3347 #endif
ashleymills 0:714293de3836 3348
ashleymills 0:714293de3836 3349
ashleymills 0:714293de3836 3350 /* Set Date validity from now until now + daysValid */
ashleymills 0:714293de3836 3351 static int SetValidity(byte* output, int daysValid)
ashleymills 0:714293de3836 3352 {
ashleymills 0:714293de3836 3353 byte before[MAX_DATE_SIZE];
ashleymills 0:714293de3836 3354 byte after[MAX_DATE_SIZE];
ashleymills 0:714293de3836 3355
ashleymills 0:714293de3836 3356 int beforeSz;
ashleymills 0:714293de3836 3357 int afterSz;
ashleymills 0:714293de3836 3358 int seqSz;
ashleymills 0:714293de3836 3359
ashleymills 0:714293de3836 3360 time_t ticks;
ashleymills 0:714293de3836 3361 struct tm* now;
ashleymills 0:714293de3836 3362 struct tm local;
ashleymills 0:714293de3836 3363
ashleymills 0:714293de3836 3364 ticks = XTIME(0);
ashleymills 0:714293de3836 3365 now = XGMTIME(&ticks);
ashleymills 0:714293de3836 3366
ashleymills 0:714293de3836 3367 /* before now */
ashleymills 0:714293de3836 3368 local = *now;
ashleymills 0:714293de3836 3369 before[0] = ASN_GENERALIZED_TIME;
ashleymills 0:714293de3836 3370 beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */
ashleymills 0:714293de3836 3371
ashleymills 0:714293de3836 3372 /* subtract 1 day for more compliance */
ashleymills 0:714293de3836 3373 local.tm_mday -= 1;
ashleymills 0:714293de3836 3374 mktime(&local);
ashleymills 0:714293de3836 3375
ashleymills 0:714293de3836 3376 /* adjust */
ashleymills 0:714293de3836 3377 local.tm_year += 1900;
ashleymills 0:714293de3836 3378 local.tm_mon += 1;
ashleymills 0:714293de3836 3379
ashleymills 0:714293de3836 3380 SetTime(&local, before + beforeSz);
ashleymills 0:714293de3836 3381 beforeSz += ASN_GEN_TIME_SZ;
ashleymills 0:714293de3836 3382
ashleymills 0:714293de3836 3383 /* after now + daysValid */
ashleymills 0:714293de3836 3384 local = *now;
ashleymills 0:714293de3836 3385 after[0] = ASN_GENERALIZED_TIME;
ashleymills 0:714293de3836 3386 afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */
ashleymills 0:714293de3836 3387
ashleymills 0:714293de3836 3388 /* add daysValid */
ashleymills 0:714293de3836 3389 local.tm_mday += daysValid;
ashleymills 0:714293de3836 3390 mktime(&local);
ashleymills 0:714293de3836 3391
ashleymills 0:714293de3836 3392 /* adjust */
ashleymills 0:714293de3836 3393 local.tm_year += 1900;
ashleymills 0:714293de3836 3394 local.tm_mon += 1;
ashleymills 0:714293de3836 3395
ashleymills 0:714293de3836 3396 SetTime(&local, after + afterSz);
ashleymills 0:714293de3836 3397 afterSz += ASN_GEN_TIME_SZ;
ashleymills 0:714293de3836 3398
ashleymills 0:714293de3836 3399 /* headers and output */
ashleymills 0:714293de3836 3400 seqSz = SetSequence(beforeSz + afterSz, output);
ashleymills 0:714293de3836 3401 XMEMCPY(output + seqSz, before, beforeSz);
ashleymills 0:714293de3836 3402 XMEMCPY(output + seqSz + beforeSz, after, afterSz);
ashleymills 0:714293de3836 3403
ashleymills 0:714293de3836 3404 return seqSz + beforeSz + afterSz;
ashleymills 0:714293de3836 3405 }
ashleymills 0:714293de3836 3406
ashleymills 0:714293de3836 3407
ashleymills 0:714293de3836 3408 /* ASN Encoded Name field */
ashleymills 0:714293de3836 3409 typedef struct EncodedName {
ashleymills 0:714293de3836 3410 int nameLen; /* actual string value length */
ashleymills 0:714293de3836 3411 int totalLen; /* total encoded length */
ashleymills 0:714293de3836 3412 int type; /* type of name */
ashleymills 0:714293de3836 3413 int used; /* are we actually using this one */
ashleymills 0:714293de3836 3414 byte encoded[CTC_NAME_SIZE * 2]; /* encoding */
ashleymills 0:714293de3836 3415 } EncodedName;
ashleymills 0:714293de3836 3416
ashleymills 0:714293de3836 3417
ashleymills 0:714293de3836 3418 /* Get Which Name from index */
ashleymills 0:714293de3836 3419 static const char* GetOneName(CertName* name, int idx)
ashleymills 0:714293de3836 3420 {
ashleymills 0:714293de3836 3421 switch (idx) {
ashleymills 0:714293de3836 3422 case 0:
ashleymills 0:714293de3836 3423 return name->country;
ashleymills 0:714293de3836 3424
ashleymills 0:714293de3836 3425 case 1:
ashleymills 0:714293de3836 3426 return name->state;
ashleymills 0:714293de3836 3427
ashleymills 0:714293de3836 3428 case 2:
ashleymills 0:714293de3836 3429 return name->locality;
ashleymills 0:714293de3836 3430
ashleymills 0:714293de3836 3431 case 3:
ashleymills 0:714293de3836 3432 return name->sur;
ashleymills 0:714293de3836 3433
ashleymills 0:714293de3836 3434 case 4:
ashleymills 0:714293de3836 3435 return name->org;
ashleymills 0:714293de3836 3436
ashleymills 0:714293de3836 3437 case 5:
ashleymills 0:714293de3836 3438 return name->unit;
ashleymills 0:714293de3836 3439
ashleymills 0:714293de3836 3440 case 6:
ashleymills 0:714293de3836 3441 return name->commonName;
ashleymills 0:714293de3836 3442
ashleymills 0:714293de3836 3443 case 7:
ashleymills 0:714293de3836 3444 return name->email;
ashleymills 0:714293de3836 3445
ashleymills 0:714293de3836 3446 default:
ashleymills 0:714293de3836 3447 return 0;
ashleymills 0:714293de3836 3448 }
ashleymills 0:714293de3836 3449 }
ashleymills 0:714293de3836 3450
ashleymills 0:714293de3836 3451
ashleymills 0:714293de3836 3452 /* Get ASN Name from index */
ashleymills 0:714293de3836 3453 static byte GetNameId(int idx)
ashleymills 0:714293de3836 3454 {
ashleymills 0:714293de3836 3455 switch (idx) {
ashleymills 0:714293de3836 3456 case 0:
ashleymills 0:714293de3836 3457 return ASN_COUNTRY_NAME;
ashleymills 0:714293de3836 3458
ashleymills 0:714293de3836 3459 case 1:
ashleymills 0:714293de3836 3460 return ASN_STATE_NAME;
ashleymills 0:714293de3836 3461
ashleymills 0:714293de3836 3462 case 2:
ashleymills 0:714293de3836 3463 return ASN_LOCALITY_NAME;
ashleymills 0:714293de3836 3464
ashleymills 0:714293de3836 3465 case 3:
ashleymills 0:714293de3836 3466 return ASN_SUR_NAME;
ashleymills 0:714293de3836 3467
ashleymills 0:714293de3836 3468 case 4:
ashleymills 0:714293de3836 3469 return ASN_ORG_NAME;
ashleymills 0:714293de3836 3470
ashleymills 0:714293de3836 3471 case 5:
ashleymills 0:714293de3836 3472 return ASN_ORGUNIT_NAME;
ashleymills 0:714293de3836 3473
ashleymills 0:714293de3836 3474 case 6:
ashleymills 0:714293de3836 3475 return ASN_COMMON_NAME;
ashleymills 0:714293de3836 3476
ashleymills 0:714293de3836 3477 case 7:
ashleymills 0:714293de3836 3478 /* email uses different id type */
ashleymills 0:714293de3836 3479 return 0;
ashleymills 0:714293de3836 3480
ashleymills 0:714293de3836 3481 default:
ashleymills 0:714293de3836 3482 return 0;
ashleymills 0:714293de3836 3483 }
ashleymills 0:714293de3836 3484 }
ashleymills 0:714293de3836 3485
ashleymills 0:714293de3836 3486
ashleymills 0:714293de3836 3487 /* encode all extensions, return total bytes written */
ashleymills 0:714293de3836 3488 static int SetExtensions(byte* output, const byte* ext, int extSz)
ashleymills 0:714293de3836 3489 {
ashleymills 0:714293de3836 3490 byte sequence[MAX_SEQ_SZ];
ashleymills 0:714293de3836 3491 byte len[MAX_LENGTH_SZ];
ashleymills 0:714293de3836 3492
ashleymills 0:714293de3836 3493 int sz = 0;
ashleymills 0:714293de3836 3494 int seqSz = SetSequence(extSz, sequence);
ashleymills 0:714293de3836 3495 int lenSz = SetLength(seqSz + extSz, len);
ashleymills 0:714293de3836 3496
ashleymills 0:714293de3836 3497 output[0] = ASN_EXTENSIONS; /* extensions id */
ashleymills 0:714293de3836 3498 sz++;
ashleymills 0:714293de3836 3499 XMEMCPY(&output[sz], len, lenSz); /* length */
ashleymills 0:714293de3836 3500 sz += lenSz;
ashleymills 0:714293de3836 3501 XMEMCPY(&output[sz], sequence, seqSz); /* sequence */
ashleymills 0:714293de3836 3502 sz += seqSz;
ashleymills 0:714293de3836 3503 XMEMCPY(&output[sz], ext, extSz); /* extensions */
ashleymills 0:714293de3836 3504 sz += extSz;
ashleymills 0:714293de3836 3505
ashleymills 0:714293de3836 3506 return sz;
ashleymills 0:714293de3836 3507 }
ashleymills 0:714293de3836 3508
ashleymills 0:714293de3836 3509
ashleymills 0:714293de3836 3510 /* encode CA basic constraint true, return total bytes written */
ashleymills 0:714293de3836 3511 static int SetCa(byte* output)
ashleymills 0:714293de3836 3512 {
ashleymills 0:714293de3836 3513 static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
ashleymills 0:714293de3836 3514 0x05, 0x30, 0x03, 0x01, 0x01, 0xff };
ashleymills 0:714293de3836 3515
ashleymills 0:714293de3836 3516 XMEMCPY(output, ca, sizeof(ca));
ashleymills 0:714293de3836 3517
ashleymills 0:714293de3836 3518 return (int)sizeof(ca);
ashleymills 0:714293de3836 3519 }
ashleymills 0:714293de3836 3520
ashleymills 0:714293de3836 3521
ashleymills 0:714293de3836 3522 /* encode CertName into output, return total bytes written */
ashleymills 0:714293de3836 3523 static int SetName(byte* output, CertName* name)
ashleymills 0:714293de3836 3524 {
ashleymills 0:714293de3836 3525 int totalBytes = 0, i, idx;
ashleymills 0:714293de3836 3526 EncodedName names[NAME_ENTRIES];
ashleymills 0:714293de3836 3527
ashleymills 0:714293de3836 3528 for (i = 0; i < NAME_ENTRIES; i++) {
ashleymills 0:714293de3836 3529 const char* nameStr = GetOneName(name, i);
ashleymills 0:714293de3836 3530 if (nameStr) {
ashleymills 0:714293de3836 3531 /* bottom up */
ashleymills 0:714293de3836 3532 byte firstLen[MAX_LENGTH_SZ];
ashleymills 0:714293de3836 3533 byte secondLen[MAX_LENGTH_SZ];
ashleymills 0:714293de3836 3534 byte sequence[MAX_SEQ_SZ];
ashleymills 0:714293de3836 3535 byte set[MAX_SET_SZ];
ashleymills 0:714293de3836 3536
ashleymills 0:714293de3836 3537 int email = i == (NAME_ENTRIES - 1) ? 1 : 0;
ashleymills 0:714293de3836 3538 int strLen = (int)XSTRLEN(nameStr);
ashleymills 0:714293de3836 3539 int thisLen = strLen;
ashleymills 0:714293de3836 3540 int firstSz, secondSz, seqSz, setSz;
ashleymills 0:714293de3836 3541
ashleymills 0:714293de3836 3542 if (strLen == 0) { /* no user data for this item */
ashleymills 0:714293de3836 3543 names[i].used = 0;
ashleymills 0:714293de3836 3544 continue;
ashleymills 0:714293de3836 3545 }
ashleymills 0:714293de3836 3546
ashleymills 0:714293de3836 3547 secondSz = SetLength(strLen, secondLen);
ashleymills 0:714293de3836 3548 thisLen += secondSz;
ashleymills 0:714293de3836 3549 if (email) {
ashleymills 0:714293de3836 3550 thisLen += EMAIL_JOINT_LEN;
ashleymills 0:714293de3836 3551 thisLen ++; /* id type */
ashleymills 0:714293de3836 3552 firstSz = SetLength(EMAIL_JOINT_LEN, firstLen);
ashleymills 0:714293de3836 3553 }
ashleymills 0:714293de3836 3554 else {
ashleymills 0:714293de3836 3555 thisLen++; /* str type */
ashleymills 0:714293de3836 3556 thisLen++; /* id type */
ashleymills 0:714293de3836 3557 thisLen += JOINT_LEN;
ashleymills 0:714293de3836 3558 firstSz = SetLength(JOINT_LEN + 1, firstLen);
ashleymills 0:714293de3836 3559 }
ashleymills 0:714293de3836 3560 thisLen += firstSz;
ashleymills 0:714293de3836 3561 thisLen++; /* object id */
ashleymills 0:714293de3836 3562
ashleymills 0:714293de3836 3563 seqSz = SetSequence(thisLen, sequence);
ashleymills 0:714293de3836 3564 thisLen += seqSz;
ashleymills 0:714293de3836 3565 setSz = SetSet(thisLen, set);
ashleymills 0:714293de3836 3566 thisLen += setSz;
ashleymills 0:714293de3836 3567
ashleymills 0:714293de3836 3568 if (thisLen > (int)sizeof(names[i].encoded))
ashleymills 0:714293de3836 3569 return BUFFER_E;
ashleymills 0:714293de3836 3570
ashleymills 0:714293de3836 3571 /* store it */
ashleymills 0:714293de3836 3572 idx = 0;
ashleymills 0:714293de3836 3573 /* set */
ashleymills 0:714293de3836 3574 XMEMCPY(names[i].encoded, set, setSz);
ashleymills 0:714293de3836 3575 idx += setSz;
ashleymills 0:714293de3836 3576 /* seq */
ashleymills 0:714293de3836 3577 XMEMCPY(names[i].encoded + idx, sequence, seqSz);
ashleymills 0:714293de3836 3578 idx += seqSz;
ashleymills 0:714293de3836 3579 /* asn object id */
ashleymills 0:714293de3836 3580 names[i].encoded[idx++] = ASN_OBJECT_ID;
ashleymills 0:714293de3836 3581 /* first length */
ashleymills 0:714293de3836 3582 XMEMCPY(names[i].encoded + idx, firstLen, firstSz);
ashleymills 0:714293de3836 3583 idx += firstSz;
ashleymills 0:714293de3836 3584 if (email) {
ashleymills 0:714293de3836 3585 const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
ashleymills 0:714293de3836 3586 0x01, 0x09, 0x01, 0x16 };
ashleymills 0:714293de3836 3587 /* email joint id */
ashleymills 0:714293de3836 3588 XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
ashleymills 0:714293de3836 3589 idx += (int)sizeof(EMAIL_OID);
ashleymills 0:714293de3836 3590 }
ashleymills 0:714293de3836 3591 else {
ashleymills 0:714293de3836 3592 /* joint id */
ashleymills 0:714293de3836 3593 names[i].encoded[idx++] = 0x55;
ashleymills 0:714293de3836 3594 names[i].encoded[idx++] = 0x04;
ashleymills 0:714293de3836 3595 /* id type */
ashleymills 0:714293de3836 3596 names[i].encoded[idx++] = GetNameId(i);
ashleymills 0:714293de3836 3597 /* str type */
ashleymills 0:714293de3836 3598 names[i].encoded[idx++] = 0x13;
ashleymills 0:714293de3836 3599 }
ashleymills 0:714293de3836 3600 /* second length */
ashleymills 0:714293de3836 3601 XMEMCPY(names[i].encoded + idx, secondLen, secondSz);
ashleymills 0:714293de3836 3602 idx += secondSz;
ashleymills 0:714293de3836 3603 /* str value */
ashleymills 0:714293de3836 3604 XMEMCPY(names[i].encoded + idx, nameStr, strLen);
ashleymills 0:714293de3836 3605 idx += strLen;
ashleymills 0:714293de3836 3606
ashleymills 0:714293de3836 3607 totalBytes += idx;
ashleymills 0:714293de3836 3608 names[i].totalLen = idx;
ashleymills 0:714293de3836 3609 names[i].used = 1;
ashleymills 0:714293de3836 3610 }
ashleymills 0:714293de3836 3611 else
ashleymills 0:714293de3836 3612 names[i].used = 0;
ashleymills 0:714293de3836 3613 }
ashleymills 0:714293de3836 3614
ashleymills 0:714293de3836 3615 /* header */
ashleymills 0:714293de3836 3616 idx = SetSequence(totalBytes, output);
ashleymills 0:714293de3836 3617 totalBytes += idx;
ashleymills 0:714293de3836 3618 if (totalBytes > ASN_NAME_MAX)
ashleymills 0:714293de3836 3619 return BUFFER_E;
ashleymills 0:714293de3836 3620
ashleymills 0:714293de3836 3621 for (i = 0; i < NAME_ENTRIES; i++) {
ashleymills 0:714293de3836 3622 if (names[i].used) {
ashleymills 0:714293de3836 3623 XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
ashleymills 0:714293de3836 3624 idx += names[i].totalLen;
ashleymills 0:714293de3836 3625 }
ashleymills 0:714293de3836 3626 }
ashleymills 0:714293de3836 3627 return totalBytes;
ashleymills 0:714293de3836 3628 }
ashleymills 0:714293de3836 3629
ashleymills 0:714293de3836 3630 /* encode info from cert into DER enocder format */
ashleymills 0:714293de3836 3631 static int EncodeCert(
ashleymills 0:714293de3836 3632 Cert* cert,
ashleymills 0:714293de3836 3633 DerCert* der,
ashleymills 0:714293de3836 3634 RsaKey* rsaKey,
ashleymills 0:714293de3836 3635 RNG* rng,
ashleymills 0:714293de3836 3636 const byte* ntruKey,
ashleymills 0:714293de3836 3637 word16 ntruSz)
ashleymills 0:714293de3836 3638 {
ashleymills 0:714293de3836 3639 (void)ntruKey;
ashleymills 0:714293de3836 3640 (void)ntruSz;
ashleymills 0:714293de3836 3641
ashleymills 0:714293de3836 3642 /* init */
ashleymills 0:714293de3836 3643 XMEMSET(der, 0, sizeof(DerCert));
ashleymills 0:714293de3836 3644
ashleymills 0:714293de3836 3645 /* version */
ashleymills 0:714293de3836 3646 der->versionSz = SetMyVersion(cert->version, der->version, TRUE);
ashleymills 0:714293de3836 3647
ashleymills 0:714293de3836 3648 /* serial number */
ashleymills 0:714293de3836 3649 RNG_GenerateBlock(rng, cert->serial, CTC_SERIAL_SIZE);
ashleymills 0:714293de3836 3650 cert->serial[0] = 0x01; /* ensure positive */
ashleymills 0:714293de3836 3651 der->serialSz = SetSerial(cert->serial, der->serial);
ashleymills 0:714293de3836 3652
ashleymills 0:714293de3836 3653 /* signature algo */
ashleymills 0:714293de3836 3654 der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType);
ashleymills 0:714293de3836 3655 if (der->sigAlgoSz == 0)
ashleymills 0:714293de3836 3656 return ALGO_ID_E;
ashleymills 0:714293de3836 3657
ashleymills 0:714293de3836 3658 /* public key */
ashleymills 0:714293de3836 3659 if (cert->keyType == RSA_KEY) {
ashleymills 0:714293de3836 3660 der->publicKeySz = SetPublicKey(der->publicKey, rsaKey);
ashleymills 0:714293de3836 3661 if (der->publicKeySz == 0)
ashleymills 0:714293de3836 3662 return PUBLIC_KEY_E;
ashleymills 0:714293de3836 3663 }
ashleymills 0:714293de3836 3664 else {
ashleymills 0:714293de3836 3665 #ifdef HAVE_NTRU
ashleymills 0:714293de3836 3666 word32 rc;
ashleymills 0:714293de3836 3667 word16 encodedSz;
ashleymills 0:714293de3836 3668
ashleymills 0:714293de3836 3669 rc = crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
ashleymills 0:714293de3836 3670 ntruKey, &encodedSz, NULL);
ashleymills 0:714293de3836 3671 if (rc != NTRU_OK)
ashleymills 0:714293de3836 3672 return PUBLIC_KEY_E;
ashleymills 0:714293de3836 3673 if (encodedSz > MAX_PUBLIC_KEY_SZ)
ashleymills 0:714293de3836 3674 return PUBLIC_KEY_E;
ashleymills 0:714293de3836 3675
ashleymills 0:714293de3836 3676 rc = crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
ashleymills 0:714293de3836 3677 ntruKey, &encodedSz, der->publicKey);
ashleymills 0:714293de3836 3678 if (rc != NTRU_OK)
ashleymills 0:714293de3836 3679 return PUBLIC_KEY_E;
ashleymills 0:714293de3836 3680
ashleymills 0:714293de3836 3681 der->publicKeySz = encodedSz;
ashleymills 0:714293de3836 3682 #endif
ashleymills 0:714293de3836 3683 }
ashleymills 0:714293de3836 3684
ashleymills 0:714293de3836 3685 der->validitySz = 0;
ashleymills 0:714293de3836 3686 #ifdef CYASSL_ALT_NAMES
ashleymills 0:714293de3836 3687 /* date validity copy ? */
ashleymills 0:714293de3836 3688 if (cert->beforeDateSz && cert->afterDateSz) {
ashleymills 0:714293de3836 3689 der->validitySz = CopyValidity(der->validity, cert);
ashleymills 0:714293de3836 3690 if (der->validitySz == 0)
ashleymills 0:714293de3836 3691 return DATE_E;
ashleymills 0:714293de3836 3692 }
ashleymills 0:714293de3836 3693 #endif
ashleymills 0:714293de3836 3694
ashleymills 0:714293de3836 3695 /* date validity */
ashleymills 0:714293de3836 3696 if (der->validitySz == 0) {
ashleymills 0:714293de3836 3697 der->validitySz = SetValidity(der->validity, cert->daysValid);
ashleymills 0:714293de3836 3698 if (der->validitySz == 0)
ashleymills 0:714293de3836 3699 return DATE_E;
ashleymills 0:714293de3836 3700 }
ashleymills 0:714293de3836 3701
ashleymills 0:714293de3836 3702 /* subject name */
ashleymills 0:714293de3836 3703 der->subjectSz = SetName(der->subject, &cert->subject);
ashleymills 0:714293de3836 3704 if (der->subjectSz == 0)
ashleymills 0:714293de3836 3705 return SUBJECT_E;
ashleymills 0:714293de3836 3706
ashleymills 0:714293de3836 3707 /* issuer name */
ashleymills 0:714293de3836 3708 der->issuerSz = SetName(der->issuer, cert->selfSigned ?
ashleymills 0:714293de3836 3709 &cert->subject : &cert->issuer);
ashleymills 0:714293de3836 3710 if (der->issuerSz == 0)
ashleymills 0:714293de3836 3711 return ISSUER_E;
ashleymills 0:714293de3836 3712
ashleymills 0:714293de3836 3713 /* CA */
ashleymills 0:714293de3836 3714 if (cert->isCA) {
ashleymills 0:714293de3836 3715 der->caSz = SetCa(der->ca);
ashleymills 0:714293de3836 3716 if (der->caSz == 0)
ashleymills 0:714293de3836 3717 return CA_TRUE_E;
ashleymills 0:714293de3836 3718 }
ashleymills 0:714293de3836 3719 else
ashleymills 0:714293de3836 3720 der->caSz = 0;
ashleymills 0:714293de3836 3721
ashleymills 0:714293de3836 3722 /* extensions, just CA now */
ashleymills 0:714293de3836 3723 if (cert->isCA) {
ashleymills 0:714293de3836 3724 der->extensionsSz = SetExtensions(der->extensions, der->ca, der->caSz);
ashleymills 0:714293de3836 3725 if (der->extensionsSz == 0)
ashleymills 0:714293de3836 3726 return EXTENSIONS_E;
ashleymills 0:714293de3836 3727 }
ashleymills 0:714293de3836 3728 else
ashleymills 0:714293de3836 3729 der->extensionsSz = 0;
ashleymills 0:714293de3836 3730
ashleymills 0:714293de3836 3731 #ifdef CYASSL_ALT_NAMES
ashleymills 0:714293de3836 3732 if (der->extensionsSz == 0 && cert->altNamesSz) {
ashleymills 0:714293de3836 3733 der->extensionsSz = SetExtensions(der->extensions, cert->altNames,
ashleymills 0:714293de3836 3734 cert->altNamesSz);
ashleymills 0:714293de3836 3735 if (der->extensionsSz == 0)
ashleymills 0:714293de3836 3736 return EXTENSIONS_E;
ashleymills 0:714293de3836 3737 }
ashleymills 0:714293de3836 3738 #endif
ashleymills 0:714293de3836 3739
ashleymills 0:714293de3836 3740 der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
ashleymills 0:714293de3836 3741 der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz +
ashleymills 0:714293de3836 3742 der->extensionsSz;
ashleymills 0:714293de3836 3743
ashleymills 0:714293de3836 3744 return 0;
ashleymills 0:714293de3836 3745 }
ashleymills 0:714293de3836 3746
ashleymills 0:714293de3836 3747
ashleymills 0:714293de3836 3748 /* write DER encoded cert to buffer, size already checked */
ashleymills 0:714293de3836 3749 static int WriteCertBody(DerCert* der, byte* buffer)
ashleymills 0:714293de3836 3750 {
ashleymills 0:714293de3836 3751 int idx;
ashleymills 0:714293de3836 3752
ashleymills 0:714293de3836 3753 /* signed part header */
ashleymills 0:714293de3836 3754 idx = SetSequence(der->total, buffer);
ashleymills 0:714293de3836 3755 /* version */
ashleymills 0:714293de3836 3756 XMEMCPY(buffer + idx, der->version, der->versionSz);
ashleymills 0:714293de3836 3757 idx += der->versionSz;
ashleymills 0:714293de3836 3758 /* serial */
ashleymills 0:714293de3836 3759 XMEMCPY(buffer + idx, der->serial, der->serialSz);
ashleymills 0:714293de3836 3760 idx += der->serialSz;
ashleymills 0:714293de3836 3761 /* sig algo */
ashleymills 0:714293de3836 3762 XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz);
ashleymills 0:714293de3836 3763 idx += der->sigAlgoSz;
ashleymills 0:714293de3836 3764 /* issuer */
ashleymills 0:714293de3836 3765 XMEMCPY(buffer + idx, der->issuer, der->issuerSz);
ashleymills 0:714293de3836 3766 idx += der->issuerSz;
ashleymills 0:714293de3836 3767 /* validity */
ashleymills 0:714293de3836 3768 XMEMCPY(buffer + idx, der->validity, der->validitySz);
ashleymills 0:714293de3836 3769 idx += der->validitySz;
ashleymills 0:714293de3836 3770 /* subject */
ashleymills 0:714293de3836 3771 XMEMCPY(buffer + idx, der->subject, der->subjectSz);
ashleymills 0:714293de3836 3772 idx += der->subjectSz;
ashleymills 0:714293de3836 3773 /* public key */
ashleymills 0:714293de3836 3774 XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
ashleymills 0:714293de3836 3775 idx += der->publicKeySz;
ashleymills 0:714293de3836 3776 if (der->extensionsSz) {
ashleymills 0:714293de3836 3777 /* extensions */
ashleymills 0:714293de3836 3778 XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
ashleymills 0:714293de3836 3779 sizeof(der->extensions)));
ashleymills 0:714293de3836 3780 idx += der->extensionsSz;
ashleymills 0:714293de3836 3781 }
ashleymills 0:714293de3836 3782
ashleymills 0:714293de3836 3783 return idx;
ashleymills 0:714293de3836 3784 }
ashleymills 0:714293de3836 3785
ashleymills 0:714293de3836 3786
ashleymills 0:714293de3836 3787 /* Make RSA signature from buffer (sz), write to sig (sigSz) */
ashleymills 0:714293de3836 3788 static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz,
ashleymills 0:714293de3836 3789 RsaKey* key, RNG* rng, int sigAlgoType)
ashleymills 0:714293de3836 3790 {
ashleymills 0:714293de3836 3791 byte digest[SHA256_DIGEST_SIZE]; /* max size */
ashleymills 0:714293de3836 3792 byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ];
ashleymills 0:714293de3836 3793 int encSigSz, digestSz, typeH;
ashleymills 0:714293de3836 3794
ashleymills 0:714293de3836 3795 if (sigAlgoType == CTC_MD5wRSA) {
ashleymills 0:714293de3836 3796 Md5 md5;
ashleymills 0:714293de3836 3797 InitMd5(&md5);
ashleymills 0:714293de3836 3798 Md5Update(&md5, buffer, sz);
ashleymills 0:714293de3836 3799 Md5Final(&md5, digest);
ashleymills 0:714293de3836 3800 digestSz = MD5_DIGEST_SIZE;
ashleymills 0:714293de3836 3801 typeH = MD5h;
ashleymills 0:714293de3836 3802 }
ashleymills 0:714293de3836 3803 else if (sigAlgoType == CTC_SHAwRSA) {
ashleymills 0:714293de3836 3804 Sha sha;
ashleymills 0:714293de3836 3805 InitSha(&sha);
ashleymills 0:714293de3836 3806 ShaUpdate(&sha, buffer, sz);
ashleymills 0:714293de3836 3807 ShaFinal(&sha, digest);
ashleymills 0:714293de3836 3808 digestSz = SHA_DIGEST_SIZE;
ashleymills 0:714293de3836 3809 typeH = SHAh;
ashleymills 0:714293de3836 3810 }
ashleymills 0:714293de3836 3811 else if (sigAlgoType == CTC_SHA256wRSA) {
ashleymills 0:714293de3836 3812 Sha256 sha256;
ashleymills 0:714293de3836 3813 InitSha256(&sha256);
ashleymills 0:714293de3836 3814 Sha256Update(&sha256, buffer, sz);
ashleymills 0:714293de3836 3815 Sha256Final(&sha256, digest);
ashleymills 0:714293de3836 3816 digestSz = SHA256_DIGEST_SIZE;
ashleymills 0:714293de3836 3817 typeH = SHA256h;
ashleymills 0:714293de3836 3818 }
ashleymills 0:714293de3836 3819 else
ashleymills 0:714293de3836 3820 return ALGO_ID_E;
ashleymills 0:714293de3836 3821
ashleymills 0:714293de3836 3822 /* signature */
ashleymills 0:714293de3836 3823 encSigSz = EncodeSignature(encSig, digest, digestSz, typeH);
ashleymills 0:714293de3836 3824 return RsaSSL_Sign(encSig, encSigSz, sig, sigSz, key, rng);
ashleymills 0:714293de3836 3825 }
ashleymills 0:714293de3836 3826
ashleymills 0:714293de3836 3827
ashleymills 0:714293de3836 3828 /* add signature to end of buffer, size of buffer assumed checked, return
ashleymills 0:714293de3836 3829 new length */
ashleymills 0:714293de3836 3830 static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
ashleymills 0:714293de3836 3831 int sigAlgoType)
ashleymills 0:714293de3836 3832 {
ashleymills 0:714293de3836 3833 byte seq[MAX_SEQ_SZ];
ashleymills 0:714293de3836 3834 int idx = bodySz, seqSz;
ashleymills 0:714293de3836 3835
ashleymills 0:714293de3836 3836 /* algo */
ashleymills 0:714293de3836 3837 idx += SetAlgoID(sigAlgoType, buffer + idx, sigType);
ashleymills 0:714293de3836 3838 /* bit string */
ashleymills 0:714293de3836 3839 buffer[idx++] = ASN_BIT_STRING;
ashleymills 0:714293de3836 3840 /* length */
ashleymills 0:714293de3836 3841 idx += SetLength(sigSz + 1, buffer + idx);
ashleymills 0:714293de3836 3842 buffer[idx++] = 0; /* trailing 0 */
ashleymills 0:714293de3836 3843 /* signature */
ashleymills 0:714293de3836 3844 XMEMCPY(buffer + idx, sig, sigSz);
ashleymills 0:714293de3836 3845 idx += sigSz;
ashleymills 0:714293de3836 3846
ashleymills 0:714293de3836 3847 /* make room for overall header */
ashleymills 0:714293de3836 3848 seqSz = SetSequence(idx, seq);
ashleymills 0:714293de3836 3849 XMEMMOVE(buffer + seqSz, buffer, idx);
ashleymills 0:714293de3836 3850 XMEMCPY(buffer, seq, seqSz);
ashleymills 0:714293de3836 3851
ashleymills 0:714293de3836 3852 return idx + seqSz;
ashleymills 0:714293de3836 3853 }
ashleymills 0:714293de3836 3854
ashleymills 0:714293de3836 3855
ashleymills 0:714293de3836 3856 /* Make an x509 Certificate v3 any key type from cert input, write to buffer */
ashleymills 0:714293de3836 3857 static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
ashleymills 0:714293de3836 3858 RsaKey* rsaKey, RNG* rng, const byte* ntruKey, word16 ntruSz)
ashleymills 0:714293de3836 3859 {
ashleymills 0:714293de3836 3860 DerCert der;
ashleymills 0:714293de3836 3861 int ret;
ashleymills 0:714293de3836 3862
ashleymills 0:714293de3836 3863 cert->keyType = rsaKey ? RSA_KEY : NTRU_KEY;
ashleymills 0:714293de3836 3864 ret = EncodeCert(cert, &der, rsaKey, rng, ntruKey, ntruSz);
ashleymills 0:714293de3836 3865 if (ret != 0)
ashleymills 0:714293de3836 3866 return ret;
ashleymills 0:714293de3836 3867
ashleymills 0:714293de3836 3868 if (der.total + MAX_SEQ_SZ * 2 > (int)derSz)
ashleymills 0:714293de3836 3869 return BUFFER_E;
ashleymills 0:714293de3836 3870
ashleymills 0:714293de3836 3871 return cert->bodySz = WriteCertBody(&der, derBuffer);
ashleymills 0:714293de3836 3872 }
ashleymills 0:714293de3836 3873
ashleymills 0:714293de3836 3874
ashleymills 0:714293de3836 3875 /* Make an x509 Certificate v3 RSA from cert input, write to buffer */
ashleymills 0:714293de3836 3876 int MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,RNG* rng)
ashleymills 0:714293de3836 3877 {
ashleymills 0:714293de3836 3878 return MakeAnyCert(cert, derBuffer, derSz, rsaKey, rng, NULL, 0);
ashleymills 0:714293de3836 3879 }
ashleymills 0:714293de3836 3880
ashleymills 0:714293de3836 3881
ashleymills 0:714293de3836 3882 #ifdef HAVE_NTRU
ashleymills 0:714293de3836 3883
ashleymills 0:714293de3836 3884 int MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
ashleymills 0:714293de3836 3885 const byte* ntruKey, word16 keySz, RNG* rng)
ashleymills 0:714293de3836 3886 {
ashleymills 0:714293de3836 3887 return MakeAnyCert(cert, derBuffer, derSz, NULL, rng, ntruKey, keySz);
ashleymills 0:714293de3836 3888 }
ashleymills 0:714293de3836 3889
ashleymills 0:714293de3836 3890 #endif /* HAVE_NTRU */
ashleymills 0:714293de3836 3891
ashleymills 0:714293de3836 3892
ashleymills 0:714293de3836 3893 int SignCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
ashleymills 0:714293de3836 3894 {
ashleymills 0:714293de3836 3895 byte sig[MAX_ENCODED_SIG_SZ];
ashleymills 0:714293de3836 3896 int sigSz;
ashleymills 0:714293de3836 3897 int bodySz = cert->bodySz;
ashleymills 0:714293de3836 3898
ashleymills 0:714293de3836 3899 if (bodySz < 0)
ashleymills 0:714293de3836 3900 return bodySz;
ashleymills 0:714293de3836 3901
ashleymills 0:714293de3836 3902 sigSz = MakeSignature(buffer, bodySz, sig, sizeof(sig), key, rng,
ashleymills 0:714293de3836 3903 cert->sigType);
ashleymills 0:714293de3836 3904 if (sigSz < 0)
ashleymills 0:714293de3836 3905 return sigSz;
ashleymills 0:714293de3836 3906
ashleymills 0:714293de3836 3907 if (bodySz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz)
ashleymills 0:714293de3836 3908 return BUFFER_E;
ashleymills 0:714293de3836 3909
ashleymills 0:714293de3836 3910 return AddSignature(buffer, bodySz, sig, sigSz, cert->sigType);
ashleymills 0:714293de3836 3911 }
ashleymills 0:714293de3836 3912
ashleymills 0:714293de3836 3913
ashleymills 0:714293de3836 3914 int MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
ashleymills 0:714293de3836 3915 {
ashleymills 0:714293de3836 3916 int ret = MakeCert(cert, buffer, buffSz, key, rng);
ashleymills 0:714293de3836 3917
ashleymills 0:714293de3836 3918 if (ret < 0)
ashleymills 0:714293de3836 3919 return ret;
ashleymills 0:714293de3836 3920
ashleymills 0:714293de3836 3921 return SignCert(cert, buffer, buffSz, key, rng);
ashleymills 0:714293de3836 3922 }
ashleymills 0:714293de3836 3923
ashleymills 0:714293de3836 3924
ashleymills 0:714293de3836 3925 #ifdef CYASSL_ALT_NAMES
ashleymills 0:714293de3836 3926
ashleymills 0:714293de3836 3927 /* Set Alt Names from der cert, return 0 on success */
ashleymills 0:714293de3836 3928 static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
ashleymills 0:714293de3836 3929 {
ashleymills 0:714293de3836 3930 DecodedCert decoded;
ashleymills 0:714293de3836 3931 int ret;
ashleymills 0:714293de3836 3932
ashleymills 0:714293de3836 3933 if (derSz < 0)
ashleymills 0:714293de3836 3934 return derSz;
ashleymills 0:714293de3836 3935
ashleymills 0:714293de3836 3936 InitDecodedCert(&decoded, (byte*)der, derSz, 0);
ashleymills 0:714293de3836 3937 ret = ParseCertRelative(&decoded, CA_TYPE, NO_VERIFY, 0);
ashleymills 0:714293de3836 3938
ashleymills 0:714293de3836 3939 if (ret < 0) {
ashleymills 0:714293de3836 3940 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 3941 return ret;
ashleymills 0:714293de3836 3942 }
ashleymills 0:714293de3836 3943
ashleymills 0:714293de3836 3944 if (decoded.extensions) {
ashleymills 0:714293de3836 3945 byte b;
ashleymills 0:714293de3836 3946 int length;
ashleymills 0:714293de3836 3947 word32 maxExtensionsIdx;
ashleymills 0:714293de3836 3948
ashleymills 0:714293de3836 3949 decoded.srcIdx = decoded.extensionsIdx;
ashleymills 0:714293de3836 3950 b = decoded.source[decoded.srcIdx++];
ashleymills 0:714293de3836 3951 if (b != ASN_EXTENSIONS) {
ashleymills 0:714293de3836 3952 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 3953 return ASN_PARSE_E;
ashleymills 0:714293de3836 3954 }
ashleymills 0:714293de3836 3955
ashleymills 0:714293de3836 3956 if (GetLength(decoded.source, &decoded.srcIdx, &length,
ashleymills 0:714293de3836 3957 decoded.maxIdx) < 0) {
ashleymills 0:714293de3836 3958 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 3959 return ASN_PARSE_E;
ashleymills 0:714293de3836 3960 }
ashleymills 0:714293de3836 3961
ashleymills 0:714293de3836 3962 if (GetSequence(decoded.source, &decoded.srcIdx, &length,
ashleymills 0:714293de3836 3963 decoded.maxIdx) < 0) {
ashleymills 0:714293de3836 3964 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 3965 return ASN_PARSE_E;
ashleymills 0:714293de3836 3966 }
ashleymills 0:714293de3836 3967
ashleymills 0:714293de3836 3968 maxExtensionsIdx = decoded.srcIdx + length;
ashleymills 0:714293de3836 3969
ashleymills 0:714293de3836 3970 while (decoded.srcIdx < maxExtensionsIdx) {
ashleymills 0:714293de3836 3971 word32 oid;
ashleymills 0:714293de3836 3972 word32 startIdx = decoded.srcIdx;
ashleymills 0:714293de3836 3973 word32 tmpIdx;
ashleymills 0:714293de3836 3974
ashleymills 0:714293de3836 3975 if (GetSequence(decoded.source, &decoded.srcIdx, &length,
ashleymills 0:714293de3836 3976 decoded.maxIdx) < 0) {
ashleymills 0:714293de3836 3977 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 3978 return ASN_PARSE_E;
ashleymills 0:714293de3836 3979 }
ashleymills 0:714293de3836 3980
ashleymills 0:714293de3836 3981 tmpIdx = decoded.srcIdx;
ashleymills 0:714293de3836 3982 decoded.srcIdx = startIdx;
ashleymills 0:714293de3836 3983
ashleymills 0:714293de3836 3984 if (GetAlgoId(decoded.source, &decoded.srcIdx, &oid,
ashleymills 0:714293de3836 3985 decoded.maxIdx) < 0) {
ashleymills 0:714293de3836 3986 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 3987 return ASN_PARSE_E;
ashleymills 0:714293de3836 3988 }
ashleymills 0:714293de3836 3989
ashleymills 0:714293de3836 3990 if (oid == ALT_NAMES_OID) {
ashleymills 0:714293de3836 3991 cert->altNamesSz = length + (tmpIdx - startIdx);
ashleymills 0:714293de3836 3992
ashleymills 0:714293de3836 3993 if (cert->altNamesSz < (int)sizeof(cert->altNames))
ashleymills 0:714293de3836 3994 XMEMCPY(cert->altNames, &decoded.source[startIdx],
ashleymills 0:714293de3836 3995 cert->altNamesSz);
ashleymills 0:714293de3836 3996 else {
ashleymills 0:714293de3836 3997 cert->altNamesSz = 0;
ashleymills 0:714293de3836 3998 CYASSL_MSG("AltNames extensions too big");
ashleymills 0:714293de3836 3999 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 4000 return ALT_NAME_E;
ashleymills 0:714293de3836 4001 }
ashleymills 0:714293de3836 4002 }
ashleymills 0:714293de3836 4003 decoded.srcIdx = tmpIdx + length;
ashleymills 0:714293de3836 4004 }
ashleymills 0:714293de3836 4005 }
ashleymills 0:714293de3836 4006 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 4007
ashleymills 0:714293de3836 4008 return 0;
ashleymills 0:714293de3836 4009 }
ashleymills 0:714293de3836 4010
ashleymills 0:714293de3836 4011
ashleymills 0:714293de3836 4012 /* Set Dates from der cert, return 0 on success */
ashleymills 0:714293de3836 4013 static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
ashleymills 0:714293de3836 4014 {
ashleymills 0:714293de3836 4015 DecodedCert decoded;
ashleymills 0:714293de3836 4016 int ret;
ashleymills 0:714293de3836 4017
ashleymills 0:714293de3836 4018 CYASSL_ENTER("SetDatesFromCert");
ashleymills 0:714293de3836 4019 if (derSz < 0)
ashleymills 0:714293de3836 4020 return derSz;
ashleymills 0:714293de3836 4021
ashleymills 0:714293de3836 4022 InitDecodedCert(&decoded, (byte*)der, derSz, 0);
ashleymills 0:714293de3836 4023 ret = ParseCertRelative(&decoded, CA_TYPE, NO_VERIFY, 0);
ashleymills 0:714293de3836 4024
ashleymills 0:714293de3836 4025 if (ret < 0) {
ashleymills 0:714293de3836 4026 CYASSL_MSG("ParseCertRelative error");
ashleymills 0:714293de3836 4027 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 4028 return ret;
ashleymills 0:714293de3836 4029 }
ashleymills 0:714293de3836 4030
ashleymills 0:714293de3836 4031 if (decoded.beforeDate == NULL || decoded.afterDate == NULL) {
ashleymills 0:714293de3836 4032 CYASSL_MSG("Couldn't extract dates");
ashleymills 0:714293de3836 4033 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 4034 return -1;
ashleymills 0:714293de3836 4035 }
ashleymills 0:714293de3836 4036
ashleymills 0:714293de3836 4037 if (decoded.beforeDateLen > MAX_DATE_SIZE || decoded.afterDateLen >
ashleymills 0:714293de3836 4038 MAX_DATE_SIZE) {
ashleymills 0:714293de3836 4039 CYASSL_MSG("Bad date size");
ashleymills 0:714293de3836 4040 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 4041 return -1;
ashleymills 0:714293de3836 4042 }
ashleymills 0:714293de3836 4043
ashleymills 0:714293de3836 4044 XMEMCPY(cert->beforeDate, decoded.beforeDate, decoded.beforeDateLen);
ashleymills 0:714293de3836 4045 XMEMCPY(cert->afterDate, decoded.afterDate, decoded.afterDateLen);
ashleymills 0:714293de3836 4046
ashleymills 0:714293de3836 4047 cert->beforeDateSz = decoded.beforeDateLen;
ashleymills 0:714293de3836 4048 cert->afterDateSz = decoded.afterDateLen;
ashleymills 0:714293de3836 4049
ashleymills 0:714293de3836 4050 return 0;
ashleymills 0:714293de3836 4051 }
ashleymills 0:714293de3836 4052
ashleymills 0:714293de3836 4053
ashleymills 0:714293de3836 4054 #endif /* CYASSL_ALT_NAMES && !NO_RSA */
ashleymills 0:714293de3836 4055
ashleymills 0:714293de3836 4056
ashleymills 0:714293de3836 4057 /* Set cn name from der buffer, return 0 on success */
ashleymills 0:714293de3836 4058 static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
ashleymills 0:714293de3836 4059 {
ashleymills 0:714293de3836 4060 DecodedCert decoded;
ashleymills 0:714293de3836 4061 int ret;
ashleymills 0:714293de3836 4062 int sz;
ashleymills 0:714293de3836 4063
ashleymills 0:714293de3836 4064 if (derSz < 0)
ashleymills 0:714293de3836 4065 return derSz;
ashleymills 0:714293de3836 4066
ashleymills 0:714293de3836 4067 InitDecodedCert(&decoded, (byte*)der, derSz, 0);
ashleymills 0:714293de3836 4068 ret = ParseCertRelative(&decoded, CA_TYPE, NO_VERIFY, 0);
ashleymills 0:714293de3836 4069
ashleymills 0:714293de3836 4070 if (ret < 0)
ashleymills 0:714293de3836 4071 return ret;
ashleymills 0:714293de3836 4072
ashleymills 0:714293de3836 4073 if (decoded.subjectCN) {
ashleymills 0:714293de3836 4074 sz = (decoded.subjectCNLen < CTC_NAME_SIZE) ? decoded.subjectCNLen :
ashleymills 0:714293de3836 4075 CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4076 strncpy(cn->commonName, decoded.subjectCN, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4077 cn->commonName[sz] = 0;
ashleymills 0:714293de3836 4078 }
ashleymills 0:714293de3836 4079 if (decoded.subjectC) {
ashleymills 0:714293de3836 4080 sz = (decoded.subjectCLen < CTC_NAME_SIZE) ? decoded.subjectCLen :
ashleymills 0:714293de3836 4081 CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4082 strncpy(cn->country, decoded.subjectC, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4083 cn->country[sz] = 0;
ashleymills 0:714293de3836 4084 }
ashleymills 0:714293de3836 4085 if (decoded.subjectST) {
ashleymills 0:714293de3836 4086 sz = (decoded.subjectSTLen < CTC_NAME_SIZE) ? decoded.subjectSTLen :
ashleymills 0:714293de3836 4087 CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4088 strncpy(cn->state, decoded.subjectST, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4089 cn->state[sz] = 0;
ashleymills 0:714293de3836 4090 }
ashleymills 0:714293de3836 4091 if (decoded.subjectL) {
ashleymills 0:714293de3836 4092 sz = (decoded.subjectLLen < CTC_NAME_SIZE) ? decoded.subjectLLen :
ashleymills 0:714293de3836 4093 CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4094 strncpy(cn->locality, decoded.subjectL, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4095 cn->locality[sz] = 0;
ashleymills 0:714293de3836 4096 }
ashleymills 0:714293de3836 4097 if (decoded.subjectO) {
ashleymills 0:714293de3836 4098 sz = (decoded.subjectOLen < CTC_NAME_SIZE) ? decoded.subjectOLen :
ashleymills 0:714293de3836 4099 CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4100 strncpy(cn->org, decoded.subjectO, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4101 cn->org[sz] = 0;
ashleymills 0:714293de3836 4102 }
ashleymills 0:714293de3836 4103 if (decoded.subjectOU) {
ashleymills 0:714293de3836 4104 sz = (decoded.subjectOULen < CTC_NAME_SIZE) ? decoded.subjectOULen :
ashleymills 0:714293de3836 4105 CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4106 strncpy(cn->unit, decoded.subjectOU, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4107 cn->unit[sz] = 0;
ashleymills 0:714293de3836 4108 }
ashleymills 0:714293de3836 4109 if (decoded.subjectSN) {
ashleymills 0:714293de3836 4110 sz = (decoded.subjectSNLen < CTC_NAME_SIZE) ? decoded.subjectSNLen :
ashleymills 0:714293de3836 4111 CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4112 strncpy(cn->sur, decoded.subjectSN, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4113 cn->sur[sz] = 0;
ashleymills 0:714293de3836 4114 }
ashleymills 0:714293de3836 4115 if (decoded.subjectEmail) {
ashleymills 0:714293de3836 4116 sz = (decoded.subjectEmailLen < CTC_NAME_SIZE) ?
ashleymills 0:714293de3836 4117 decoded.subjectEmailLen : CTC_NAME_SIZE - 1;
ashleymills 0:714293de3836 4118 strncpy(cn->email, decoded.subjectEmail, CTC_NAME_SIZE);
ashleymills 0:714293de3836 4119 cn->email[sz] = 0;
ashleymills 0:714293de3836 4120 }
ashleymills 0:714293de3836 4121
ashleymills 0:714293de3836 4122 FreeDecodedCert(&decoded);
ashleymills 0:714293de3836 4123
ashleymills 0:714293de3836 4124 return 0;
ashleymills 0:714293de3836 4125 }
ashleymills 0:714293de3836 4126
ashleymills 0:714293de3836 4127
ashleymills 0:714293de3836 4128 #ifndef NO_FILESYSTEM
ashleymills 0:714293de3836 4129
ashleymills 0:714293de3836 4130 /* forward from CyaSSL */
ashleymills 0:714293de3836 4131 int CyaSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz);
ashleymills 0:714293de3836 4132
ashleymills 0:714293de3836 4133 /* Set cert issuer from issuerFile in PEM */
ashleymills 0:714293de3836 4134 int SetIssuer(Cert* cert, const char* issuerFile)
ashleymills 0:714293de3836 4135 {
ashleymills 0:714293de3836 4136 int ret;
ashleymills 0:714293de3836 4137 int derSz;
ashleymills 0:714293de3836 4138 byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
ashleymills 0:714293de3836 4139
ashleymills 0:714293de3836 4140 if (der == NULL) {
ashleymills 0:714293de3836 4141 CYASSL_MSG("SetIssuer OOF Problem");
ashleymills 0:714293de3836 4142 return MEMORY_E;
ashleymills 0:714293de3836 4143 }
ashleymills 0:714293de3836 4144 derSz = CyaSSL_PemCertToDer(issuerFile, der, EIGHTK_BUF);
ashleymills 0:714293de3836 4145 cert->selfSigned = 0;
ashleymills 0:714293de3836 4146 ret = SetNameFromCert(&cert->issuer, der, derSz);
ashleymills 0:714293de3836 4147 XFREE(der, NULL, DYNAMIC_TYPE_CERT);
ashleymills 0:714293de3836 4148
ashleymills 0:714293de3836 4149 return ret;
ashleymills 0:714293de3836 4150 }
ashleymills 0:714293de3836 4151
ashleymills 0:714293de3836 4152
ashleymills 0:714293de3836 4153 /* Set cert subject from subjectFile in PEM */
ashleymills 0:714293de3836 4154 int SetSubject(Cert* cert, const char* subjectFile)
ashleymills 0:714293de3836 4155 {
ashleymills 0:714293de3836 4156 int ret;
ashleymills 0:714293de3836 4157 int derSz;
ashleymills 0:714293de3836 4158 byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
ashleymills 0:714293de3836 4159
ashleymills 0:714293de3836 4160 if (der == NULL) {
ashleymills 0:714293de3836 4161 CYASSL_MSG("SetSubject OOF Problem");
ashleymills 0:714293de3836 4162 return MEMORY_E;
ashleymills 0:714293de3836 4163 }
ashleymills 0:714293de3836 4164 derSz = CyaSSL_PemCertToDer(subjectFile, der, EIGHTK_BUF);
ashleymills 0:714293de3836 4165 ret = SetNameFromCert(&cert->subject, der, derSz);
ashleymills 0:714293de3836 4166 XFREE(der, NULL, DYNAMIC_TYPE_CERT);
ashleymills 0:714293de3836 4167
ashleymills 0:714293de3836 4168 return ret;
ashleymills 0:714293de3836 4169 }
ashleymills 0:714293de3836 4170
ashleymills 0:714293de3836 4171
ashleymills 0:714293de3836 4172 #ifdef CYASSL_ALT_NAMES
ashleymills 0:714293de3836 4173
ashleymills 0:714293de3836 4174 /* Set atl names from file in PEM */
ashleymills 0:714293de3836 4175 int SetAltNames(Cert* cert, const char* file)
ashleymills 0:714293de3836 4176 {
ashleymills 0:714293de3836 4177 int ret;
ashleymills 0:714293de3836 4178 int derSz;
ashleymills 0:714293de3836 4179 byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
ashleymills 0:714293de3836 4180
ashleymills 0:714293de3836 4181 if (der == NULL) {
ashleymills 0:714293de3836 4182 CYASSL_MSG("SetAltNames OOF Problem");
ashleymills 0:714293de3836 4183 return MEMORY_E;
ashleymills 0:714293de3836 4184 }
ashleymills 0:714293de3836 4185 derSz = CyaSSL_PemCertToDer(file, der, EIGHTK_BUF);
ashleymills 0:714293de3836 4186 ret = SetAltNamesFromCert(cert, der, derSz);
ashleymills 0:714293de3836 4187 XFREE(der, NULL, DYNAMIC_TYPE_CERT);
ashleymills 0:714293de3836 4188
ashleymills 0:714293de3836 4189 return ret;
ashleymills 0:714293de3836 4190 }
ashleymills 0:714293de3836 4191
ashleymills 0:714293de3836 4192 #endif /* CYASSL_ALT_NAMES */
ashleymills 0:714293de3836 4193
ashleymills 0:714293de3836 4194 #endif /* NO_FILESYSTEM */
ashleymills 0:714293de3836 4195
ashleymills 0:714293de3836 4196 /* Set cert issuer from DER buffer */
ashleymills 0:714293de3836 4197 int SetIssuerBuffer(Cert* cert, const byte* der, int derSz)
ashleymills 0:714293de3836 4198 {
ashleymills 0:714293de3836 4199 cert->selfSigned = 0;
ashleymills 0:714293de3836 4200 return SetNameFromCert(&cert->issuer, der, derSz);
ashleymills 0:714293de3836 4201 }
ashleymills 0:714293de3836 4202
ashleymills 0:714293de3836 4203
ashleymills 0:714293de3836 4204 /* Set cert subject from DER buffer */
ashleymills 0:714293de3836 4205 int SetSubjectBuffer(Cert* cert, const byte* der, int derSz)
ashleymills 0:714293de3836 4206 {
ashleymills 0:714293de3836 4207 return SetNameFromCert(&cert->subject, der, derSz);
ashleymills 0:714293de3836 4208 }
ashleymills 0:714293de3836 4209
ashleymills 0:714293de3836 4210
ashleymills 0:714293de3836 4211 #ifdef CYASSL_ALT_NAMES
ashleymills 0:714293de3836 4212
ashleymills 0:714293de3836 4213 /* Set cert alt names from DER buffer */
ashleymills 0:714293de3836 4214 int SetAltNamesBuffer(Cert* cert, const byte* der, int derSz)
ashleymills 0:714293de3836 4215 {
ashleymills 0:714293de3836 4216 return SetAltNamesFromCert(cert, der, derSz);
ashleymills 0:714293de3836 4217 }
ashleymills 0:714293de3836 4218
ashleymills 0:714293de3836 4219 /* Set cert dates from DER buffer */
ashleymills 0:714293de3836 4220 int SetDatesBuffer(Cert* cert, const byte* der, int derSz)
ashleymills 0:714293de3836 4221 {
ashleymills 0:714293de3836 4222 return SetDatesFromCert(cert, der, derSz);
ashleymills 0:714293de3836 4223 }
ashleymills 0:714293de3836 4224
ashleymills 0:714293de3836 4225 #endif /* CYASSL_ALT_NAMES */
ashleymills 0:714293de3836 4226
ashleymills 0:714293de3836 4227 #endif /* CYASSL_CERT_GEN */
ashleymills 0:714293de3836 4228
ashleymills 0:714293de3836 4229
ashleymills 0:714293de3836 4230 #ifdef HAVE_ECC
ashleymills 0:714293de3836 4231
ashleymills 0:714293de3836 4232 /* Der Encode r & s ints into out, outLen is (in/out) size */
ashleymills 0:714293de3836 4233 int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
ashleymills 0:714293de3836 4234 {
ashleymills 0:714293de3836 4235 word32 idx = 0;
ashleymills 0:714293de3836 4236 word32 rSz; /* encoding size */
ashleymills 0:714293de3836 4237 word32 sSz;
ashleymills 0:714293de3836 4238 word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
ashleymills 0:714293de3836 4239
ashleymills 0:714293de3836 4240 int rLen = mp_unsigned_bin_size(r); /* big int size */
ashleymills 0:714293de3836 4241 int sLen = mp_unsigned_bin_size(s);
ashleymills 0:714293de3836 4242 int err;
ashleymills 0:714293de3836 4243
ashleymills 0:714293de3836 4244 if (*outLen < (rLen + sLen + headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */
ashleymills 0:714293de3836 4245 return BAD_FUNC_ARG;
ashleymills 0:714293de3836 4246
ashleymills 0:714293de3836 4247 idx = SetSequence(rLen + sLen + headerSz, out);
ashleymills 0:714293de3836 4248
ashleymills 0:714293de3836 4249 /* store r */
ashleymills 0:714293de3836 4250 out[idx++] = ASN_INTEGER;
ashleymills 0:714293de3836 4251 rSz = SetLength(rLen, &out[idx]);
ashleymills 0:714293de3836 4252 idx += rSz;
ashleymills 0:714293de3836 4253 err = mp_to_unsigned_bin(r, &out[idx]);
ashleymills 0:714293de3836 4254 if (err != MP_OKAY) return err;
ashleymills 0:714293de3836 4255 idx += rLen;
ashleymills 0:714293de3836 4256
ashleymills 0:714293de3836 4257 /* store s */
ashleymills 0:714293de3836 4258 out[idx++] = ASN_INTEGER;
ashleymills 0:714293de3836 4259 sSz = SetLength(sLen, &out[idx]);
ashleymills 0:714293de3836 4260 idx += sSz;
ashleymills 0:714293de3836 4261 err = mp_to_unsigned_bin(s, &out[idx]);
ashleymills 0:714293de3836 4262 if (err != MP_OKAY) return err;
ashleymills 0:714293de3836 4263 idx += sLen;
ashleymills 0:714293de3836 4264
ashleymills 0:714293de3836 4265 *outLen = idx;
ashleymills 0:714293de3836 4266
ashleymills 0:714293de3836 4267 return 0;
ashleymills 0:714293de3836 4268 }
ashleymills 0:714293de3836 4269
ashleymills 0:714293de3836 4270
ashleymills 0:714293de3836 4271 /* Der Decode ECC-DSA Signautre, r & s stored as big ints */
ashleymills 0:714293de3836 4272 int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
ashleymills 0:714293de3836 4273 {
ashleymills 0:714293de3836 4274 word32 idx = 0;
ashleymills 0:714293de3836 4275 int len = 0;
ashleymills 0:714293de3836 4276
ashleymills 0:714293de3836 4277 if (GetSequence(sig, &idx, &len, sigLen) < 0)
ashleymills 0:714293de3836 4278 return ASN_ECC_KEY_E;
ashleymills 0:714293de3836 4279
ashleymills 0:714293de3836 4280 if ((word32)len > (sigLen - idx))
ashleymills 0:714293de3836 4281 return ASN_ECC_KEY_E;
ashleymills 0:714293de3836 4282
ashleymills 0:714293de3836 4283 if (GetInt(r, sig, &idx, sigLen) < 0)
ashleymills 0:714293de3836 4284 return ASN_ECC_KEY_E;
ashleymills 0:714293de3836 4285
ashleymills 0:714293de3836 4286 if (GetInt(s, sig, &idx, sigLen) < 0)
ashleymills 0:714293de3836 4287 return ASN_ECC_KEY_E;
ashleymills 0:714293de3836 4288
ashleymills 0:714293de3836 4289 return 0;
ashleymills 0:714293de3836 4290 }
ashleymills 0:714293de3836 4291
ashleymills 0:714293de3836 4292
ashleymills 0:714293de3836 4293 int EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
ashleymills 0:714293de3836 4294 word32 inSz)
ashleymills 0:714293de3836 4295 {
ashleymills 0:714293de3836 4296 word32 oid = 0;
ashleymills 0:714293de3836 4297 int version, length;
ashleymills 0:714293de3836 4298 int privSz, pubSz;
ashleymills 0:714293de3836 4299 byte b;
ashleymills 0:714293de3836 4300 byte priv[ECC_MAXSIZE];
ashleymills 0:714293de3836 4301 byte pub[ECC_MAXSIZE * 2 + 1]; /* public key has two parts plus header */
ashleymills 0:714293de3836 4302
ashleymills 0:714293de3836 4303 if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 4304 return ASN_PARSE_E;
ashleymills 0:714293de3836 4305
ashleymills 0:714293de3836 4306 if (GetMyVersion(input, inOutIdx, &version) < 0)
ashleymills 0:714293de3836 4307 return ASN_PARSE_E;
ashleymills 0:714293de3836 4308
ashleymills 0:714293de3836 4309 b = input[*inOutIdx];
ashleymills 0:714293de3836 4310 *inOutIdx += 1;
ashleymills 0:714293de3836 4311
ashleymills 0:714293de3836 4312 /* priv type */
ashleymills 0:714293de3836 4313 if (b != 4 && b != 6 && b != 7)
ashleymills 0:714293de3836 4314 return ASN_PARSE_E;
ashleymills 0:714293de3836 4315
ashleymills 0:714293de3836 4316 if (GetLength(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 4317 return ASN_PARSE_E;
ashleymills 0:714293de3836 4318
ashleymills 0:714293de3836 4319 /* priv key */
ashleymills 0:714293de3836 4320 privSz = length;
ashleymills 0:714293de3836 4321 XMEMCPY(priv, &input[*inOutIdx], privSz);
ashleymills 0:714293de3836 4322 *inOutIdx += length;
ashleymills 0:714293de3836 4323
ashleymills 0:714293de3836 4324 /* prefix 0, may have */
ashleymills 0:714293de3836 4325 b = input[*inOutIdx];
ashleymills 0:714293de3836 4326 if (b == ECC_PREFIX_0) {
ashleymills 0:714293de3836 4327 *inOutIdx += 1;
ashleymills 0:714293de3836 4328
ashleymills 0:714293de3836 4329 if (GetLength(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 4330 return ASN_PARSE_E;
ashleymills 0:714293de3836 4331
ashleymills 0:714293de3836 4332 /* object id */
ashleymills 0:714293de3836 4333 b = input[*inOutIdx];
ashleymills 0:714293de3836 4334 *inOutIdx += 1;
ashleymills 0:714293de3836 4335
ashleymills 0:714293de3836 4336 if (b != ASN_OBJECT_ID)
ashleymills 0:714293de3836 4337 return ASN_OBJECT_ID_E;
ashleymills 0:714293de3836 4338
ashleymills 0:714293de3836 4339 if (GetLength(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 4340 return ASN_PARSE_E;
ashleymills 0:714293de3836 4341
ashleymills 0:714293de3836 4342 while(length--) {
ashleymills 0:714293de3836 4343 oid += input[*inOutIdx];
ashleymills 0:714293de3836 4344 *inOutIdx += 1;
ashleymills 0:714293de3836 4345 }
ashleymills 0:714293de3836 4346 if (CheckCurve(oid) < 0)
ashleymills 0:714293de3836 4347 return ECC_CURVE_OID_E;
ashleymills 0:714293de3836 4348 }
ashleymills 0:714293de3836 4349
ashleymills 0:714293de3836 4350 /* prefix 1 */
ashleymills 0:714293de3836 4351 b = input[*inOutIdx];
ashleymills 0:714293de3836 4352 *inOutIdx += 1;
ashleymills 0:714293de3836 4353 if (b != ECC_PREFIX_1)
ashleymills 0:714293de3836 4354 return ASN_ECC_KEY_E;
ashleymills 0:714293de3836 4355
ashleymills 0:714293de3836 4356 if (GetLength(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 4357 return ASN_PARSE_E;
ashleymills 0:714293de3836 4358
ashleymills 0:714293de3836 4359 /* key header */
ashleymills 0:714293de3836 4360 b = input[*inOutIdx];
ashleymills 0:714293de3836 4361 *inOutIdx += 1;
ashleymills 0:714293de3836 4362 if (b != ASN_BIT_STRING)
ashleymills 0:714293de3836 4363 return ASN_BITSTR_E;
ashleymills 0:714293de3836 4364
ashleymills 0:714293de3836 4365 if (GetLength(input, inOutIdx, &length, inSz) < 0)
ashleymills 0:714293de3836 4366 return ASN_PARSE_E;
ashleymills 0:714293de3836 4367 b = input[*inOutIdx];
ashleymills 0:714293de3836 4368 *inOutIdx += 1;
ashleymills 0:714293de3836 4369 if (b != 0x00)
ashleymills 0:714293de3836 4370 return ASN_EXPECT_0_E;
ashleymills 0:714293de3836 4371
ashleymills 0:714293de3836 4372 pubSz = length - 1; /* null prefix */
ashleymills 0:714293de3836 4373 XMEMCPY(pub, &input[*inOutIdx], pubSz);
ashleymills 0:714293de3836 4374
ashleymills 0:714293de3836 4375 *inOutIdx += length;
ashleymills 0:714293de3836 4376
ashleymills 0:714293de3836 4377 return ecc_import_private_key(priv, privSz, pub, pubSz, key);
ashleymills 0:714293de3836 4378 }
ashleymills 0:714293de3836 4379
ashleymills 0:714293de3836 4380 #endif /* HAVE_ECC */
ashleymills 0:714293de3836 4381
ashleymills 0:714293de3836 4382
ashleymills 0:714293de3836 4383 #if defined(HAVE_OCSP) || defined(HAVE_CRL)
ashleymills 0:714293de3836 4384
ashleymills 0:714293de3836 4385 /* Get raw Date only, no processing, 0 on success */
ashleymills 0:714293de3836 4386 static int GetBasicDate(const byte* source, word32* idx, byte* date,
ashleymills 0:714293de3836 4387 byte* format, int maxIdx)
ashleymills 0:714293de3836 4388 {
ashleymills 0:714293de3836 4389 int length;
ashleymills 0:714293de3836 4390
ashleymills 0:714293de3836 4391 CYASSL_ENTER("GetBasicDate");
ashleymills 0:714293de3836 4392
ashleymills 0:714293de3836 4393 *format = source[*idx];
ashleymills 0:714293de3836 4394 *idx += 1;
ashleymills 0:714293de3836 4395 if (*format != ASN_UTC_TIME && *format != ASN_GENERALIZED_TIME)
ashleymills 0:714293de3836 4396 return ASN_TIME_E;
ashleymills 0:714293de3836 4397
ashleymills 0:714293de3836 4398 if (GetLength(source, idx, &length, maxIdx) < 0)
ashleymills 0:714293de3836 4399 return ASN_PARSE_E;
ashleymills 0:714293de3836 4400
ashleymills 0:714293de3836 4401 if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
ashleymills 0:714293de3836 4402 return ASN_DATE_SZ_E;
ashleymills 0:714293de3836 4403
ashleymills 0:714293de3836 4404 XMEMCPY(date, &source[*idx], length);
ashleymills 0:714293de3836 4405 *idx += length;
ashleymills 0:714293de3836 4406
ashleymills 0:714293de3836 4407 return 0;
ashleymills 0:714293de3836 4408 }
ashleymills 0:714293de3836 4409
ashleymills 0:714293de3836 4410 #endif
ashleymills 0:714293de3836 4411
ashleymills 0:714293de3836 4412
ashleymills 0:714293de3836 4413 #ifdef HAVE_OCSP
ashleymills 0:714293de3836 4414
ashleymills 0:714293de3836 4415 static int GetEnumerated(const byte* input, word32* inOutIdx, int *value)
ashleymills 0:714293de3836 4416 {
ashleymills 0:714293de3836 4417 word32 idx = *inOutIdx;
ashleymills 0:714293de3836 4418 word32 len;
ashleymills 0:714293de3836 4419
ashleymills 0:714293de3836 4420 CYASSL_ENTER("GetEnumerated");
ashleymills 0:714293de3836 4421
ashleymills 0:714293de3836 4422 *value = 0;
ashleymills 0:714293de3836 4423
ashleymills 0:714293de3836 4424 if (input[idx++] != ASN_ENUMERATED)
ashleymills 0:714293de3836 4425 return ASN_PARSE_E;
ashleymills 0:714293de3836 4426
ashleymills 0:714293de3836 4427 len = input[idx++];
ashleymills 0:714293de3836 4428 if (len > 4)
ashleymills 0:714293de3836 4429 return ASN_PARSE_E;
ashleymills 0:714293de3836 4430
ashleymills 0:714293de3836 4431 while (len--) {
ashleymills 0:714293de3836 4432 *value = *value << 8 | input[idx++];
ashleymills 0:714293de3836 4433 }
ashleymills 0:714293de3836 4434
ashleymills 0:714293de3836 4435 *inOutIdx = idx;
ashleymills 0:714293de3836 4436
ashleymills 0:714293de3836 4437 return *value;
ashleymills 0:714293de3836 4438 }
ashleymills 0:714293de3836 4439
ashleymills 0:714293de3836 4440
ashleymills 0:714293de3836 4441 static int DecodeSingleResponse(byte* source,
ashleymills 0:714293de3836 4442 word32* ioIndex, OcspResponse* resp, word32 size)
ashleymills 0:714293de3836 4443 {
ashleymills 0:714293de3836 4444 word32 idx = *ioIndex, prevIndex, oid;
ashleymills 0:714293de3836 4445 int length, wrapperSz;
ashleymills 0:714293de3836 4446 CertStatus* cs = resp->status;
ashleymills 0:714293de3836 4447
ashleymills 0:714293de3836 4448 CYASSL_ENTER("DecodeSingleResponse");
ashleymills 0:714293de3836 4449
ashleymills 0:714293de3836 4450 /* Outer wrapper of the SEQUENCE OF Single Responses. */
ashleymills 0:714293de3836 4451 if (GetSequence(source, &idx, &wrapperSz, size) < 0)
ashleymills 0:714293de3836 4452 return ASN_PARSE_E;
ashleymills 0:714293de3836 4453
ashleymills 0:714293de3836 4454 prevIndex = idx;
ashleymills 0:714293de3836 4455
ashleymills 0:714293de3836 4456 /* When making a request, we only request one status on one certificate
ashleymills 0:714293de3836 4457 * at a time. There should only be one SingleResponse */
ashleymills 0:714293de3836 4458
ashleymills 0:714293de3836 4459 /* Wrapper around the Single Response */
ashleymills 0:714293de3836 4460 if (GetSequence(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4461 return ASN_PARSE_E;
ashleymills 0:714293de3836 4462
ashleymills 0:714293de3836 4463 /* Wrapper around the CertID */
ashleymills 0:714293de3836 4464 if (GetSequence(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4465 return ASN_PARSE_E;
ashleymills 0:714293de3836 4466 /* Skip the hash algorithm */
ashleymills 0:714293de3836 4467 if (GetAlgoId(source, &idx, &oid, size) < 0)
ashleymills 0:714293de3836 4468 return ASN_PARSE_E;
ashleymills 0:714293de3836 4469 /* Save reference to the hash of CN */
ashleymills 0:714293de3836 4470 if (source[idx++] != ASN_OCTET_STRING)
ashleymills 0:714293de3836 4471 return ASN_PARSE_E;
ashleymills 0:714293de3836 4472 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4473 return ASN_PARSE_E;
ashleymills 0:714293de3836 4474 resp->issuerHash = source + idx;
ashleymills 0:714293de3836 4475 idx += length;
ashleymills 0:714293de3836 4476 /* Save reference to the hash of the issuer public key */
ashleymills 0:714293de3836 4477 if (source[idx++] != ASN_OCTET_STRING)
ashleymills 0:714293de3836 4478 return ASN_PARSE_E;
ashleymills 0:714293de3836 4479 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4480 return ASN_PARSE_E;
ashleymills 0:714293de3836 4481 resp->issuerKeyHash = source + idx;
ashleymills 0:714293de3836 4482 idx += length;
ashleymills 0:714293de3836 4483
ashleymills 0:714293de3836 4484 /* Read the serial number, it is handled as a string, not as a
ashleymills 0:714293de3836 4485 * proper number. Just XMEMCPY the data over, rather than load it
ashleymills 0:714293de3836 4486 * as an mp_int. */
ashleymills 0:714293de3836 4487 if (source[idx++] != ASN_INTEGER)
ashleymills 0:714293de3836 4488 return ASN_PARSE_E;
ashleymills 0:714293de3836 4489 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4490 return ASN_PARSE_E;
ashleymills 0:714293de3836 4491 if (length <= EXTERNAL_SERIAL_SIZE)
ashleymills 0:714293de3836 4492 {
ashleymills 0:714293de3836 4493 if (source[idx] == 0)
ashleymills 0:714293de3836 4494 {
ashleymills 0:714293de3836 4495 idx++;
ashleymills 0:714293de3836 4496 length--;
ashleymills 0:714293de3836 4497 }
ashleymills 0:714293de3836 4498 XMEMCPY(cs->serial, source + idx, length);
ashleymills 0:714293de3836 4499 cs->serialSz = length;
ashleymills 0:714293de3836 4500 }
ashleymills 0:714293de3836 4501 else
ashleymills 0:714293de3836 4502 {
ashleymills 0:714293de3836 4503 return ASN_GETINT_E;
ashleymills 0:714293de3836 4504 }
ashleymills 0:714293de3836 4505 idx += length;
ashleymills 0:714293de3836 4506
ashleymills 0:714293de3836 4507 /* CertStatus */
ashleymills 0:714293de3836 4508 switch (source[idx++])
ashleymills 0:714293de3836 4509 {
ashleymills 0:714293de3836 4510 case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
ashleymills 0:714293de3836 4511 cs->status = CERT_GOOD;
ashleymills 0:714293de3836 4512 idx++;
ashleymills 0:714293de3836 4513 break;
ashleymills 0:714293de3836 4514 case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
ashleymills 0:714293de3836 4515 cs->status = CERT_REVOKED;
ashleymills 0:714293de3836 4516 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4517 return ASN_PARSE_E;
ashleymills 0:714293de3836 4518 idx += length;
ashleymills 0:714293de3836 4519 break;
ashleymills 0:714293de3836 4520 case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN):
ashleymills 0:714293de3836 4521 cs->status = CERT_UNKNOWN;
ashleymills 0:714293de3836 4522 idx++;
ashleymills 0:714293de3836 4523 break;
ashleymills 0:714293de3836 4524 default:
ashleymills 0:714293de3836 4525 return ASN_PARSE_E;
ashleymills 0:714293de3836 4526 }
ashleymills 0:714293de3836 4527
ashleymills 0:714293de3836 4528 if (GetBasicDate(source, &idx, cs->thisDate,
ashleymills 0:714293de3836 4529 &cs->thisDateFormat, size) < 0)
ashleymills 0:714293de3836 4530 return ASN_PARSE_E;
ashleymills 0:714293de3836 4531 if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE))
ashleymills 0:714293de3836 4532 return ASN_BEFORE_DATE_E;
ashleymills 0:714293de3836 4533
ashleymills 0:714293de3836 4534 /* The following items are optional. Only check for them if there is more
ashleymills 0:714293de3836 4535 * unprocessed data in the singleResponse wrapper. */
ashleymills 0:714293de3836 4536
ashleymills 0:714293de3836 4537 if (((int)(idx - prevIndex) < wrapperSz) &&
ashleymills 0:714293de3836 4538 (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)))
ashleymills 0:714293de3836 4539 {
ashleymills 0:714293de3836 4540 idx++;
ashleymills 0:714293de3836 4541 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4542 return ASN_PARSE_E;
ashleymills 0:714293de3836 4543 if (GetBasicDate(source, &idx, cs->nextDate,
ashleymills 0:714293de3836 4544 &cs->nextDateFormat, size) < 0)
ashleymills 0:714293de3836 4545 return ASN_PARSE_E;
ashleymills 0:714293de3836 4546 }
ashleymills 0:714293de3836 4547 if (((int)(idx - prevIndex) < wrapperSz) &&
ashleymills 0:714293de3836 4548 (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)))
ashleymills 0:714293de3836 4549 {
ashleymills 0:714293de3836 4550 idx++;
ashleymills 0:714293de3836 4551 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4552 return ASN_PARSE_E;
ashleymills 0:714293de3836 4553 idx += length;
ashleymills 0:714293de3836 4554 }
ashleymills 0:714293de3836 4555
ashleymills 0:714293de3836 4556 *ioIndex = idx;
ashleymills 0:714293de3836 4557
ashleymills 0:714293de3836 4558 return 0;
ashleymills 0:714293de3836 4559 }
ashleymills 0:714293de3836 4560
ashleymills 0:714293de3836 4561 static int DecodeOcspRespExtensions(byte* source,
ashleymills 0:714293de3836 4562 word32* ioIndex, OcspResponse* resp, word32 sz)
ashleymills 0:714293de3836 4563 {
ashleymills 0:714293de3836 4564 word32 idx = *ioIndex;
ashleymills 0:714293de3836 4565 int length;
ashleymills 0:714293de3836 4566 int ext_bound; /* boundary index for the sequence of extensions */
ashleymills 0:714293de3836 4567 word32 oid;
ashleymills 0:714293de3836 4568
ashleymills 0:714293de3836 4569 CYASSL_ENTER("DecodeOcspRespExtensions");
ashleymills 0:714293de3836 4570
ashleymills 0:714293de3836 4571 if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
ashleymills 0:714293de3836 4572 return ASN_PARSE_E;
ashleymills 0:714293de3836 4573
ashleymills 0:714293de3836 4574 if (GetLength(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
ashleymills 0:714293de3836 4575
ashleymills 0:714293de3836 4576 if (GetSequence(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
ashleymills 0:714293de3836 4577
ashleymills 0:714293de3836 4578 ext_bound = idx + length;
ashleymills 0:714293de3836 4579
ashleymills 0:714293de3836 4580 while (idx < (word32)ext_bound) {
ashleymills 0:714293de3836 4581 if (GetSequence(source, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 4582 CYASSL_MSG("\tfail: should be a SEQUENCE");
ashleymills 0:714293de3836 4583 return ASN_PARSE_E;
ashleymills 0:714293de3836 4584 }
ashleymills 0:714293de3836 4585
ashleymills 0:714293de3836 4586 oid = 0;
ashleymills 0:714293de3836 4587 if (GetObjectId(source, &idx, &oid, sz) < 0) {
ashleymills 0:714293de3836 4588 CYASSL_MSG("\tfail: OBJECT ID");
ashleymills 0:714293de3836 4589 return ASN_PARSE_E;
ashleymills 0:714293de3836 4590 }
ashleymills 0:714293de3836 4591
ashleymills 0:714293de3836 4592 /* check for critical flag */
ashleymills 0:714293de3836 4593 if (source[idx] == ASN_BOOLEAN) {
ashleymills 0:714293de3836 4594 CYASSL_MSG("\tfound optional critical flag, moving past");
ashleymills 0:714293de3836 4595 idx += (ASN_BOOL_SIZE + 1);
ashleymills 0:714293de3836 4596 }
ashleymills 0:714293de3836 4597
ashleymills 0:714293de3836 4598 /* process the extension based on the OID */
ashleymills 0:714293de3836 4599 if (source[idx++] != ASN_OCTET_STRING) {
ashleymills 0:714293de3836 4600 CYASSL_MSG("\tfail: should be an OCTET STRING");
ashleymills 0:714293de3836 4601 return ASN_PARSE_E;
ashleymills 0:714293de3836 4602 }
ashleymills 0:714293de3836 4603
ashleymills 0:714293de3836 4604 if (GetLength(source, &idx, &length, sz) < 0) {
ashleymills 0:714293de3836 4605 CYASSL_MSG("\tfail: extension data length");
ashleymills 0:714293de3836 4606 return ASN_PARSE_E;
ashleymills 0:714293de3836 4607 }
ashleymills 0:714293de3836 4608
ashleymills 0:714293de3836 4609 if (oid == OCSP_NONCE_OID) {
ashleymills 0:714293de3836 4610 resp->nonce = source + idx;
ashleymills 0:714293de3836 4611 resp->nonceSz = length;
ashleymills 0:714293de3836 4612 }
ashleymills 0:714293de3836 4613
ashleymills 0:714293de3836 4614 idx += length;
ashleymills 0:714293de3836 4615 }
ashleymills 0:714293de3836 4616
ashleymills 0:714293de3836 4617 *ioIndex = idx;
ashleymills 0:714293de3836 4618 return 0;
ashleymills 0:714293de3836 4619 }
ashleymills 0:714293de3836 4620
ashleymills 0:714293de3836 4621
ashleymills 0:714293de3836 4622 static int DecodeResponseData(byte* source,
ashleymills 0:714293de3836 4623 word32* ioIndex, OcspResponse* resp, word32 size)
ashleymills 0:714293de3836 4624 {
ashleymills 0:714293de3836 4625 word32 idx = *ioIndex, prev_idx;
ashleymills 0:714293de3836 4626 int length;
ashleymills 0:714293de3836 4627 int version;
ashleymills 0:714293de3836 4628 word32 responderId = 0;
ashleymills 0:714293de3836 4629
ashleymills 0:714293de3836 4630 CYASSL_ENTER("DecodeResponseData");
ashleymills 0:714293de3836 4631
ashleymills 0:714293de3836 4632 resp->response = source + idx;
ashleymills 0:714293de3836 4633 prev_idx = idx;
ashleymills 0:714293de3836 4634 if (GetSequence(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4635 return ASN_PARSE_E;
ashleymills 0:714293de3836 4636 resp->responseSz = length + idx - prev_idx;
ashleymills 0:714293de3836 4637
ashleymills 0:714293de3836 4638 /* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this
ashleymills 0:714293de3836 4639 * item isn't an EXPLICIT[0], then set version to zero and move
ashleymills 0:714293de3836 4640 * onto the next item.
ashleymills 0:714293de3836 4641 */
ashleymills 0:714293de3836 4642 if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
ashleymills 0:714293de3836 4643 {
ashleymills 0:714293de3836 4644 idx += 2; /* Eat the value and length */
ashleymills 0:714293de3836 4645 if (GetMyVersion(source, &idx, &version) < 0)
ashleymills 0:714293de3836 4646 return ASN_PARSE_E;
ashleymills 0:714293de3836 4647 } else
ashleymills 0:714293de3836 4648 version = 0;
ashleymills 0:714293de3836 4649
ashleymills 0:714293de3836 4650 responderId = source[idx++];
ashleymills 0:714293de3836 4651 if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
ashleymills 0:714293de3836 4652 (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
ashleymills 0:714293de3836 4653 {
ashleymills 0:714293de3836 4654 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4655 return ASN_PARSE_E;
ashleymills 0:714293de3836 4656 idx += length;
ashleymills 0:714293de3836 4657 }
ashleymills 0:714293de3836 4658 else
ashleymills 0:714293de3836 4659 return ASN_PARSE_E;
ashleymills 0:714293de3836 4660
ashleymills 0:714293de3836 4661 /* save pointer to the producedAt time */
ashleymills 0:714293de3836 4662 if (GetBasicDate(source, &idx, resp->producedDate,
ashleymills 0:714293de3836 4663 &resp->producedDateFormat, size) < 0)
ashleymills 0:714293de3836 4664 return ASN_PARSE_E;
ashleymills 0:714293de3836 4665
ashleymills 0:714293de3836 4666 if (DecodeSingleResponse(source, &idx, resp, size) < 0)
ashleymills 0:714293de3836 4667 return ASN_PARSE_E;
ashleymills 0:714293de3836 4668
ashleymills 0:714293de3836 4669 if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
ashleymills 0:714293de3836 4670 return ASN_PARSE_E;
ashleymills 0:714293de3836 4671
ashleymills 0:714293de3836 4672 *ioIndex = idx;
ashleymills 0:714293de3836 4673 return 0;
ashleymills 0:714293de3836 4674 }
ashleymills 0:714293de3836 4675
ashleymills 0:714293de3836 4676
ashleymills 0:714293de3836 4677 static int DecodeCerts(byte* source,
ashleymills 0:714293de3836 4678 word32* ioIndex, OcspResponse* resp, word32 size)
ashleymills 0:714293de3836 4679 {
ashleymills 0:714293de3836 4680 word32 idx = *ioIndex;
ashleymills 0:714293de3836 4681
ashleymills 0:714293de3836 4682 CYASSL_ENTER("DecodeCerts");
ashleymills 0:714293de3836 4683
ashleymills 0:714293de3836 4684 if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
ashleymills 0:714293de3836 4685 {
ashleymills 0:714293de3836 4686 int length;
ashleymills 0:714293de3836 4687
ashleymills 0:714293de3836 4688 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4689 return ASN_PARSE_E;
ashleymills 0:714293de3836 4690
ashleymills 0:714293de3836 4691 if (GetSequence(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4692 return ASN_PARSE_E;
ashleymills 0:714293de3836 4693
ashleymills 0:714293de3836 4694 resp->cert = source + idx;
ashleymills 0:714293de3836 4695 resp->certSz = length;
ashleymills 0:714293de3836 4696
ashleymills 0:714293de3836 4697 idx += length;
ashleymills 0:714293de3836 4698 }
ashleymills 0:714293de3836 4699 *ioIndex = idx;
ashleymills 0:714293de3836 4700 return 0;
ashleymills 0:714293de3836 4701 }
ashleymills 0:714293de3836 4702
ashleymills 0:714293de3836 4703 static int DecodeBasicOcspResponse(byte* source,
ashleymills 0:714293de3836 4704 word32* ioIndex, OcspResponse* resp, word32 size)
ashleymills 0:714293de3836 4705 {
ashleymills 0:714293de3836 4706 int length;
ashleymills 0:714293de3836 4707 word32 idx = *ioIndex;
ashleymills 0:714293de3836 4708 word32 end_index;
ashleymills 0:714293de3836 4709
ashleymills 0:714293de3836 4710 CYASSL_ENTER("DecodeBasicOcspResponse");
ashleymills 0:714293de3836 4711
ashleymills 0:714293de3836 4712 if (GetSequence(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4713 return ASN_PARSE_E;
ashleymills 0:714293de3836 4714
ashleymills 0:714293de3836 4715 if (idx + length > size)
ashleymills 0:714293de3836 4716 return ASN_INPUT_E;
ashleymills 0:714293de3836 4717 end_index = idx + length;
ashleymills 0:714293de3836 4718
ashleymills 0:714293de3836 4719 if (DecodeResponseData(source, &idx, resp, size) < 0)
ashleymills 0:714293de3836 4720 return ASN_PARSE_E;
ashleymills 0:714293de3836 4721
ashleymills 0:714293de3836 4722 /* Get the signature algorithm */
ashleymills 0:714293de3836 4723 if (GetAlgoId(source, &idx, &resp->sigOID, size) < 0)
ashleymills 0:714293de3836 4724 return ASN_PARSE_E;
ashleymills 0:714293de3836 4725
ashleymills 0:714293de3836 4726 /* Obtain pointer to the start of the signature, and save the size */
ashleymills 0:714293de3836 4727 if (source[idx++] == ASN_BIT_STRING)
ashleymills 0:714293de3836 4728 {
ashleymills 0:714293de3836 4729 int sigLength = 0;
ashleymills 0:714293de3836 4730 if (GetLength(source, &idx, &sigLength, size) < 0)
ashleymills 0:714293de3836 4731 return ASN_PARSE_E;
ashleymills 0:714293de3836 4732 resp->sigSz = sigLength;
ashleymills 0:714293de3836 4733 resp->sig = source + idx;
ashleymills 0:714293de3836 4734 idx += sigLength;
ashleymills 0:714293de3836 4735 }
ashleymills 0:714293de3836 4736
ashleymills 0:714293de3836 4737 /*
ashleymills 0:714293de3836 4738 * Check the length of the BasicOcspResponse against the current index to
ashleymills 0:714293de3836 4739 * see if there are certificates, they are optional.
ashleymills 0:714293de3836 4740 */
ashleymills 0:714293de3836 4741 if (idx < end_index)
ashleymills 0:714293de3836 4742 {
ashleymills 0:714293de3836 4743 DecodedCert cert;
ashleymills 0:714293de3836 4744 int ret;
ashleymills 0:714293de3836 4745
ashleymills 0:714293de3836 4746 if (DecodeCerts(source, &idx, resp, size) < 0)
ashleymills 0:714293de3836 4747 return ASN_PARSE_E;
ashleymills 0:714293de3836 4748
ashleymills 0:714293de3836 4749 InitDecodedCert(&cert, resp->cert, resp->certSz, 0);
ashleymills 0:714293de3836 4750 ret = ParseCertRelative(&cert, CA_TYPE, NO_VERIFY, 0);
ashleymills 0:714293de3836 4751 if (ret < 0)
ashleymills 0:714293de3836 4752 return ret;
ashleymills 0:714293de3836 4753
ashleymills 0:714293de3836 4754 ret = ConfirmSignature(resp->response, resp->responseSz,
ashleymills 0:714293de3836 4755 cert.publicKey, cert.pubKeySize, cert.keyOID,
ashleymills 0:714293de3836 4756 resp->sig, resp->sigSz, resp->sigOID, NULL);
ashleymills 0:714293de3836 4757 FreeDecodedCert(&cert);
ashleymills 0:714293de3836 4758
ashleymills 0:714293de3836 4759 if (ret == 0)
ashleymills 0:714293de3836 4760 {
ashleymills 0:714293de3836 4761 CYASSL_MSG("\tOCSP Confirm signature failed");
ashleymills 0:714293de3836 4762 return ASN_OCSP_CONFIRM_E;
ashleymills 0:714293de3836 4763 }
ashleymills 0:714293de3836 4764 }
ashleymills 0:714293de3836 4765
ashleymills 0:714293de3836 4766 *ioIndex = idx;
ashleymills 0:714293de3836 4767 return 0;
ashleymills 0:714293de3836 4768 }
ashleymills 0:714293de3836 4769
ashleymills 0:714293de3836 4770
ashleymills 0:714293de3836 4771 void InitOcspResponse(OcspResponse* resp, CertStatus* status,
ashleymills 0:714293de3836 4772 byte* source, word32 inSz)
ashleymills 0:714293de3836 4773 {
ashleymills 0:714293de3836 4774 CYASSL_ENTER("InitOcspResponse");
ashleymills 0:714293de3836 4775
ashleymills 0:714293de3836 4776 resp->responseStatus = -1;
ashleymills 0:714293de3836 4777 resp->response = NULL;
ashleymills 0:714293de3836 4778 resp->responseSz = 0;
ashleymills 0:714293de3836 4779 resp->producedDateFormat = 0;
ashleymills 0:714293de3836 4780 resp->issuerHash = NULL;
ashleymills 0:714293de3836 4781 resp->issuerKeyHash = NULL;
ashleymills 0:714293de3836 4782 resp->sig = NULL;
ashleymills 0:714293de3836 4783 resp->sigSz = 0;
ashleymills 0:714293de3836 4784 resp->sigOID = 0;
ashleymills 0:714293de3836 4785 resp->status = status;
ashleymills 0:714293de3836 4786 resp->nonce = NULL;
ashleymills 0:714293de3836 4787 resp->nonceSz = 0;
ashleymills 0:714293de3836 4788 resp->source = source;
ashleymills 0:714293de3836 4789 resp->maxIdx = inSz;
ashleymills 0:714293de3836 4790 }
ashleymills 0:714293de3836 4791
ashleymills 0:714293de3836 4792
ashleymills 0:714293de3836 4793 int OcspResponseDecode(OcspResponse* resp)
ashleymills 0:714293de3836 4794 {
ashleymills 0:714293de3836 4795 int length = 0;
ashleymills 0:714293de3836 4796 word32 idx = 0;
ashleymills 0:714293de3836 4797 byte* source = resp->source;
ashleymills 0:714293de3836 4798 word32 size = resp->maxIdx;
ashleymills 0:714293de3836 4799 word32 oid;
ashleymills 0:714293de3836 4800
ashleymills 0:714293de3836 4801 CYASSL_ENTER("OcspResponseDecode");
ashleymills 0:714293de3836 4802
ashleymills 0:714293de3836 4803 /* peel the outer SEQUENCE wrapper */
ashleymills 0:714293de3836 4804 if (GetSequence(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4805 return ASN_PARSE_E;
ashleymills 0:714293de3836 4806
ashleymills 0:714293de3836 4807 /* First get the responseStatus, an ENUMERATED */
ashleymills 0:714293de3836 4808 if (GetEnumerated(source, &idx, &resp->responseStatus) < 0)
ashleymills 0:714293de3836 4809 return ASN_PARSE_E;
ashleymills 0:714293de3836 4810
ashleymills 0:714293de3836 4811 if (resp->responseStatus != OCSP_SUCCESSFUL)
ashleymills 0:714293de3836 4812 return 0;
ashleymills 0:714293de3836 4813
ashleymills 0:714293de3836 4814 /* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
ashleymills 0:714293de3836 4815 if (idx >= size)
ashleymills 0:714293de3836 4816 return ASN_INPUT_E;
ashleymills 0:714293de3836 4817 if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
ashleymills 0:714293de3836 4818 return ASN_PARSE_E;
ashleymills 0:714293de3836 4819 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4820 return ASN_PARSE_E;
ashleymills 0:714293de3836 4821
ashleymills 0:714293de3836 4822 /* Get the responseBytes SEQUENCE */
ashleymills 0:714293de3836 4823 if (GetSequence(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4824 return ASN_PARSE_E;
ashleymills 0:714293de3836 4825
ashleymills 0:714293de3836 4826 /* Check ObjectID for the resposeBytes */
ashleymills 0:714293de3836 4827 if (GetObjectId(source, &idx, &oid, size) < 0)
ashleymills 0:714293de3836 4828 return ASN_PARSE_E;
ashleymills 0:714293de3836 4829 if (oid != OCSP_BASIC_OID)
ashleymills 0:714293de3836 4830 return ASN_PARSE_E;
ashleymills 0:714293de3836 4831 if (source[idx++] != ASN_OCTET_STRING)
ashleymills 0:714293de3836 4832 return ASN_PARSE_E;
ashleymills 0:714293de3836 4833
ashleymills 0:714293de3836 4834 if (GetLength(source, &idx, &length, size) < 0)
ashleymills 0:714293de3836 4835 return ASN_PARSE_E;
ashleymills 0:714293de3836 4836
ashleymills 0:714293de3836 4837 if (DecodeBasicOcspResponse(source, &idx, resp, size) < 0)
ashleymills 0:714293de3836 4838 return ASN_PARSE_E;
ashleymills 0:714293de3836 4839
ashleymills 0:714293de3836 4840 return 0;
ashleymills 0:714293de3836 4841 }
ashleymills 0:714293de3836 4842
ashleymills 0:714293de3836 4843
ashleymills 0:714293de3836 4844 static int SetSerialNumber(const byte* sn, word32 snSz, byte* output)
ashleymills 0:714293de3836 4845 {
ashleymills 0:714293de3836 4846 int result = 0;
ashleymills 0:714293de3836 4847
ashleymills 0:714293de3836 4848 CYASSL_ENTER("SetSerialNumber");
ashleymills 0:714293de3836 4849
ashleymills 0:714293de3836 4850 if (snSz <= EXTERNAL_SERIAL_SIZE) {
ashleymills 0:714293de3836 4851 output[0] = ASN_INTEGER;
ashleymills 0:714293de3836 4852 output[1] = snSz + 1;
ashleymills 0:714293de3836 4853 output[2] = 0;
ashleymills 0:714293de3836 4854 XMEMCPY(&output[3], sn, snSz);
ashleymills 0:714293de3836 4855 result = snSz + 3;
ashleymills 0:714293de3836 4856 }
ashleymills 0:714293de3836 4857 return result;
ashleymills 0:714293de3836 4858 }
ashleymills 0:714293de3836 4859
ashleymills 0:714293de3836 4860
ashleymills 0:714293de3836 4861 static word32 SetOcspReqExtensions(word32 extSz, byte* output,
ashleymills 0:714293de3836 4862 const byte* nonce, word32 nonceSz)
ashleymills 0:714293de3836 4863 {
ashleymills 0:714293de3836 4864 static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
ashleymills 0:714293de3836 4865 0x30, 0x01, 0x02 };
ashleymills 0:714293de3836 4866 byte seqArray[5][MAX_SEQ_SZ];
ashleymills 0:714293de3836 4867 word32 seqSz[5], totalSz;
ashleymills 0:714293de3836 4868
ashleymills 0:714293de3836 4869 CYASSL_ENTER("SetOcspReqExtensions");
ashleymills 0:714293de3836 4870
ashleymills 0:714293de3836 4871 if (nonce == NULL || nonceSz == 0) return 0;
ashleymills 0:714293de3836 4872
ashleymills 0:714293de3836 4873 seqArray[0][0] = ASN_OCTET_STRING;
ashleymills 0:714293de3836 4874 seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]);
ashleymills 0:714293de3836 4875
ashleymills 0:714293de3836 4876 seqArray[1][0] = ASN_OBJECT_ID;
ashleymills 0:714293de3836 4877 seqSz[1] = 1 + SetLength(sizeof(NonceObjId), &seqArray[1][1]);
ashleymills 0:714293de3836 4878
ashleymills 0:714293de3836 4879 totalSz = seqSz[0] + seqSz[1] + nonceSz + (word32)sizeof(NonceObjId);
ashleymills 0:714293de3836 4880
ashleymills 0:714293de3836 4881 seqSz[2] = SetSequence(totalSz, seqArray[2]);
ashleymills 0:714293de3836 4882 totalSz += seqSz[2];
ashleymills 0:714293de3836 4883
ashleymills 0:714293de3836 4884 seqSz[3] = SetSequence(totalSz, seqArray[3]);
ashleymills 0:714293de3836 4885 totalSz += seqSz[3];
ashleymills 0:714293de3836 4886
ashleymills 0:714293de3836 4887 seqArray[4][0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2);
ashleymills 0:714293de3836 4888 seqSz[4] = 1 + SetLength(totalSz, &seqArray[4][1]);
ashleymills 0:714293de3836 4889 totalSz += seqSz[4];
ashleymills 0:714293de3836 4890
ashleymills 0:714293de3836 4891 if (totalSz < extSz)
ashleymills 0:714293de3836 4892 {
ashleymills 0:714293de3836 4893 totalSz = 0;
ashleymills 0:714293de3836 4894 XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
ashleymills 0:714293de3836 4895 totalSz += seqSz[4];
ashleymills 0:714293de3836 4896 XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
ashleymills 0:714293de3836 4897 totalSz += seqSz[3];
ashleymills 0:714293de3836 4898 XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
ashleymills 0:714293de3836 4899 totalSz += seqSz[2];
ashleymills 0:714293de3836 4900 XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
ashleymills 0:714293de3836 4901 totalSz += seqSz[1];
ashleymills 0:714293de3836 4902 XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
ashleymills 0:714293de3836 4903 totalSz += (word32)sizeof(NonceObjId);
ashleymills 0:714293de3836 4904 XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
ashleymills 0:714293de3836 4905 totalSz += seqSz[0];
ashleymills 0:714293de3836 4906 XMEMCPY(output + totalSz, nonce, nonceSz);
ashleymills 0:714293de3836 4907 totalSz += nonceSz;
ashleymills 0:714293de3836 4908 }
ashleymills 0:714293de3836 4909
ashleymills 0:714293de3836 4910 return totalSz;
ashleymills 0:714293de3836 4911 }
ashleymills 0:714293de3836 4912
ashleymills 0:714293de3836 4913
ashleymills 0:714293de3836 4914 int EncodeOcspRequest(OcspRequest* req)
ashleymills 0:714293de3836 4915 {
ashleymills 0:714293de3836 4916 byte seqArray[5][MAX_SEQ_SZ];
ashleymills 0:714293de3836 4917 /* The ASN.1 of the OCSP Request is an onion of sequences */
ashleymills 0:714293de3836 4918 byte algoArray[MAX_ALGO_SZ];
ashleymills 0:714293de3836 4919 byte issuerArray[MAX_ENCODED_DIG_SZ];
ashleymills 0:714293de3836 4920 byte issuerKeyArray[MAX_ENCODED_DIG_SZ];
ashleymills 0:714293de3836 4921 byte snArray[MAX_SN_SZ];
ashleymills 0:714293de3836 4922 byte extArray[MAX_OCSP_EXT_SZ];
ashleymills 0:714293de3836 4923 byte* output = req->dest;
ashleymills 0:714293de3836 4924 word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz;
ashleymills 0:714293de3836 4925 int i;
ashleymills 0:714293de3836 4926
ashleymills 0:714293de3836 4927 CYASSL_ENTER("EncodeOcspRequest");
ashleymills 0:714293de3836 4928
ashleymills 0:714293de3836 4929 algoSz = SetAlgoID(SHAh, algoArray, hashType);
ashleymills 0:714293de3836 4930
ashleymills 0:714293de3836 4931 req->issuerHash = req->cert->issuerHash;
ashleymills 0:714293de3836 4932 issuerSz = SetDigest(req->cert->issuerHash, SHA_SIZE, issuerArray);
ashleymills 0:714293de3836 4933
ashleymills 0:714293de3836 4934 req->issuerKeyHash = req->cert->issuerKeyHash;
ashleymills 0:714293de3836 4935 issuerKeySz = SetDigest(req->cert->issuerKeyHash, SHA_SIZE, issuerKeyArray);
ashleymills 0:714293de3836 4936
ashleymills 0:714293de3836 4937 req->serial = req->cert->serial;
ashleymills 0:714293de3836 4938 req->serialSz = req->cert->serialSz;
ashleymills 0:714293de3836 4939 snSz = SetSerialNumber(req->cert->serial, req->cert->serialSz, snArray);
ashleymills 0:714293de3836 4940
ashleymills 0:714293de3836 4941 extSz = 0;
ashleymills 0:714293de3836 4942 if (req->useNonce) {
ashleymills 0:714293de3836 4943 RNG rng;
ashleymills 0:714293de3836 4944 if (InitRng(&rng) != 0) {
ashleymills 0:714293de3836 4945 CYASSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
ashleymills 0:714293de3836 4946 } else {
ashleymills 0:714293de3836 4947 req->nonceSz = MAX_OCSP_NONCE_SZ;
ashleymills 0:714293de3836 4948 RNG_GenerateBlock(&rng, req->nonce, req->nonceSz);
ashleymills 0:714293de3836 4949 extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
ashleymills 0:714293de3836 4950 req->nonce, req->nonceSz);
ashleymills 0:714293de3836 4951 }
ashleymills 0:714293de3836 4952 }
ashleymills 0:714293de3836 4953
ashleymills 0:714293de3836 4954 totalSz = algoSz + issuerSz + issuerKeySz + snSz;
ashleymills 0:714293de3836 4955
ashleymills 0:714293de3836 4956 for (i = 4; i >= 0; i--) {
ashleymills 0:714293de3836 4957 seqSz[i] = SetSequence(totalSz, seqArray[i]);
ashleymills 0:714293de3836 4958 totalSz += seqSz[i];
ashleymills 0:714293de3836 4959 if (i == 2) totalSz += extSz;
ashleymills 0:714293de3836 4960 }
ashleymills 0:714293de3836 4961 totalSz = 0;
ashleymills 0:714293de3836 4962 for (i = 0; i < 5; i++) {
ashleymills 0:714293de3836 4963 XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
ashleymills 0:714293de3836 4964 totalSz += seqSz[i];
ashleymills 0:714293de3836 4965 }
ashleymills 0:714293de3836 4966 XMEMCPY(output + totalSz, algoArray, algoSz);
ashleymills 0:714293de3836 4967 totalSz += algoSz;
ashleymills 0:714293de3836 4968 XMEMCPY(output + totalSz, issuerArray, issuerSz);
ashleymills 0:714293de3836 4969 totalSz += issuerSz;
ashleymills 0:714293de3836 4970 XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz);
ashleymills 0:714293de3836 4971 totalSz += issuerKeySz;
ashleymills 0:714293de3836 4972 XMEMCPY(output + totalSz, snArray, snSz);
ashleymills 0:714293de3836 4973 totalSz += snSz;
ashleymills 0:714293de3836 4974 if (extSz != 0) {
ashleymills 0:714293de3836 4975 XMEMCPY(output + totalSz, extArray, extSz);
ashleymills 0:714293de3836 4976 totalSz += extSz;
ashleymills 0:714293de3836 4977 }
ashleymills 0:714293de3836 4978
ashleymills 0:714293de3836 4979 return totalSz;
ashleymills 0:714293de3836 4980 }
ashleymills 0:714293de3836 4981
ashleymills 0:714293de3836 4982
ashleymills 0:714293de3836 4983 void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
ashleymills 0:714293de3836 4984 byte* dest, word32 destSz)
ashleymills 0:714293de3836 4985 {
ashleymills 0:714293de3836 4986 CYASSL_ENTER("InitOcspRequest");
ashleymills 0:714293de3836 4987
ashleymills 0:714293de3836 4988 req->cert = cert;
ashleymills 0:714293de3836 4989 req->useNonce = useNonce;
ashleymills 0:714293de3836 4990 req->nonceSz = 0;
ashleymills 0:714293de3836 4991 req->issuerHash = NULL;
ashleymills 0:714293de3836 4992 req->issuerKeyHash = NULL;
ashleymills 0:714293de3836 4993 req->serial = NULL;
ashleymills 0:714293de3836 4994 req->dest = dest;
ashleymills 0:714293de3836 4995 req->destSz = destSz;
ashleymills 0:714293de3836 4996 }
ashleymills 0:714293de3836 4997
ashleymills 0:714293de3836 4998
ashleymills 0:714293de3836 4999 int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
ashleymills 0:714293de3836 5000 {
ashleymills 0:714293de3836 5001 int cmp;
ashleymills 0:714293de3836 5002
ashleymills 0:714293de3836 5003 CYASSL_ENTER("CompareOcspReqResp");
ashleymills 0:714293de3836 5004
ashleymills 0:714293de3836 5005 if (req == NULL)
ashleymills 0:714293de3836 5006 {
ashleymills 0:714293de3836 5007 CYASSL_MSG("\tReq missing");
ashleymills 0:714293de3836 5008 return -1;
ashleymills 0:714293de3836 5009 }
ashleymills 0:714293de3836 5010
ashleymills 0:714293de3836 5011 if (resp == NULL)
ashleymills 0:714293de3836 5012 {
ashleymills 0:714293de3836 5013 CYASSL_MSG("\tResp missing");
ashleymills 0:714293de3836 5014 return 1;
ashleymills 0:714293de3836 5015 }
ashleymills 0:714293de3836 5016
ashleymills 0:714293de3836 5017 if (req->useNonce) {
ashleymills 0:714293de3836 5018 cmp = req->nonceSz - resp->nonceSz;
ashleymills 0:714293de3836 5019 if (cmp != 0)
ashleymills 0:714293de3836 5020 {
ashleymills 0:714293de3836 5021 CYASSL_MSG("\tnonceSz mismatch");
ashleymills 0:714293de3836 5022 return cmp;
ashleymills 0:714293de3836 5023 }
ashleymills 0:714293de3836 5024
ashleymills 0:714293de3836 5025 cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz);
ashleymills 0:714293de3836 5026 if (cmp != 0)
ashleymills 0:714293de3836 5027 {
ashleymills 0:714293de3836 5028 CYASSL_MSG("\tnonce mismatch");
ashleymills 0:714293de3836 5029 return cmp;
ashleymills 0:714293de3836 5030 }
ashleymills 0:714293de3836 5031 }
ashleymills 0:714293de3836 5032
ashleymills 0:714293de3836 5033 cmp = XMEMCMP(req->issuerHash, resp->issuerHash, SHA_DIGEST_SIZE);
ashleymills 0:714293de3836 5034 if (cmp != 0)
ashleymills 0:714293de3836 5035 {
ashleymills 0:714293de3836 5036 CYASSL_MSG("\tissuerHash mismatch");
ashleymills 0:714293de3836 5037 return cmp;
ashleymills 0:714293de3836 5038 }
ashleymills 0:714293de3836 5039
ashleymills 0:714293de3836 5040 cmp = XMEMCMP(req->issuerKeyHash, resp->issuerKeyHash, SHA_DIGEST_SIZE);
ashleymills 0:714293de3836 5041 if (cmp != 0)
ashleymills 0:714293de3836 5042 {
ashleymills 0:714293de3836 5043 CYASSL_MSG("\tissuerKeyHash mismatch");
ashleymills 0:714293de3836 5044 return cmp;
ashleymills 0:714293de3836 5045 }
ashleymills 0:714293de3836 5046
ashleymills 0:714293de3836 5047 cmp = req->serialSz - resp->status->serialSz;
ashleymills 0:714293de3836 5048 if (cmp != 0)
ashleymills 0:714293de3836 5049 {
ashleymills 0:714293de3836 5050 CYASSL_MSG("\tserialSz mismatch");
ashleymills 0:714293de3836 5051 return cmp;
ashleymills 0:714293de3836 5052 }
ashleymills 0:714293de3836 5053
ashleymills 0:714293de3836 5054 cmp = XMEMCMP(req->serial, resp->status->serial, req->serialSz);
ashleymills 0:714293de3836 5055 if (cmp != 0)
ashleymills 0:714293de3836 5056 {
ashleymills 0:714293de3836 5057 CYASSL_MSG("\tserial mismatch");
ashleymills 0:714293de3836 5058 return cmp;
ashleymills 0:714293de3836 5059 }
ashleymills 0:714293de3836 5060
ashleymills 0:714293de3836 5061 return 0;
ashleymills 0:714293de3836 5062 }
ashleymills 0:714293de3836 5063
ashleymills 0:714293de3836 5064 #endif
ashleymills 0:714293de3836 5065
ashleymills 0:714293de3836 5066
ashleymills 0:714293de3836 5067 #ifdef HAVE_CRL
ashleymills 0:714293de3836 5068
ashleymills 0:714293de3836 5069 /* initialize decoded CRL */
ashleymills 0:714293de3836 5070 void InitDecodedCRL(DecodedCRL* dcrl)
ashleymills 0:714293de3836 5071 {
ashleymills 0:714293de3836 5072 CYASSL_MSG("InitDecodedCRL");
ashleymills 0:714293de3836 5073
ashleymills 0:714293de3836 5074 dcrl->certBegin = 0;
ashleymills 0:714293de3836 5075 dcrl->sigIndex = 0;
ashleymills 0:714293de3836 5076 dcrl->sigLength = 0;
ashleymills 0:714293de3836 5077 dcrl->signatureOID = 0;
ashleymills 0:714293de3836 5078 dcrl->certs = NULL;
ashleymills 0:714293de3836 5079 dcrl->totalCerts = 0;
ashleymills 0:714293de3836 5080 }
ashleymills 0:714293de3836 5081
ashleymills 0:714293de3836 5082
ashleymills 0:714293de3836 5083 /* free decoded CRL resources */
ashleymills 0:714293de3836 5084 void FreeDecodedCRL(DecodedCRL* dcrl)
ashleymills 0:714293de3836 5085 {
ashleymills 0:714293de3836 5086 RevokedCert* tmp = dcrl->certs;
ashleymills 0:714293de3836 5087
ashleymills 0:714293de3836 5088 CYASSL_MSG("FreeDecodedCRL");
ashleymills 0:714293de3836 5089
ashleymills 0:714293de3836 5090 while(tmp) {
ashleymills 0:714293de3836 5091 RevokedCert* next = tmp->next;
ashleymills 0:714293de3836 5092 XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
ashleymills 0:714293de3836 5093 tmp = next;
ashleymills 0:714293de3836 5094 }
ashleymills 0:714293de3836 5095 }
ashleymills 0:714293de3836 5096
ashleymills 0:714293de3836 5097
ashleymills 0:714293de3836 5098 /* store SHA1 hash of NAME */
ashleymills 0:714293de3836 5099 static int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx)
ashleymills 0:714293de3836 5100 {
ashleymills 0:714293de3836 5101 Sha sha;
ashleymills 0:714293de3836 5102 int length; /* length of all distinguished names */
ashleymills 0:714293de3836 5103 word32 dummy;
ashleymills 0:714293de3836 5104
ashleymills 0:714293de3836 5105 CYASSL_ENTER("GetNameHash");
ashleymills 0:714293de3836 5106
ashleymills 0:714293de3836 5107 if (source[*idx] == ASN_OBJECT_ID) {
ashleymills 0:714293de3836 5108 CYASSL_MSG("Trying optional prefix...");
ashleymills 0:714293de3836 5109
ashleymills 0:714293de3836 5110 if (GetLength(source, idx, &length, maxIdx) < 0)
ashleymills 0:714293de3836 5111 return ASN_PARSE_E;
ashleymills 0:714293de3836 5112
ashleymills 0:714293de3836 5113 *idx += length;
ashleymills 0:714293de3836 5114 CYASSL_MSG("Got optional prefix");
ashleymills 0:714293de3836 5115 }
ashleymills 0:714293de3836 5116
ashleymills 0:714293de3836 5117 /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
ashleymills 0:714293de3836 5118 * calculated over the entire DER encoding of the Name field, including
ashleymills 0:714293de3836 5119 * the tag and length. */
ashleymills 0:714293de3836 5120 dummy = *idx;
ashleymills 0:714293de3836 5121 if (GetSequence(source, idx, &length, maxIdx) < 0)
ashleymills 0:714293de3836 5122 return ASN_PARSE_E;
ashleymills 0:714293de3836 5123
ashleymills 0:714293de3836 5124 InitSha(&sha);
ashleymills 0:714293de3836 5125 ShaUpdate(&sha, source + dummy, length + *idx - dummy);
ashleymills 0:714293de3836 5126 ShaFinal(&sha, hash);
ashleymills 0:714293de3836 5127
ashleymills 0:714293de3836 5128 *idx += length;
ashleymills 0:714293de3836 5129
ashleymills 0:714293de3836 5130 return 0;
ashleymills 0:714293de3836 5131 }
ashleymills 0:714293de3836 5132
ashleymills 0:714293de3836 5133
ashleymills 0:714293de3836 5134 /* Get Revoked Cert list, 0 on success */
ashleymills 0:714293de3836 5135 static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
ashleymills 0:714293de3836 5136 int maxIdx)
ashleymills 0:714293de3836 5137 {
ashleymills 0:714293de3836 5138 int len;
ashleymills 0:714293de3836 5139 word32 end;
ashleymills 0:714293de3836 5140 byte b;
ashleymills 0:714293de3836 5141 RevokedCert* rc;
ashleymills 0:714293de3836 5142
ashleymills 0:714293de3836 5143 CYASSL_ENTER("GetRevoked");
ashleymills 0:714293de3836 5144
ashleymills 0:714293de3836 5145 if (GetSequence(buff, idx, &len, maxIdx) < 0)
ashleymills 0:714293de3836 5146 return ASN_PARSE_E;
ashleymills 0:714293de3836 5147
ashleymills 0:714293de3836 5148 end = *idx + len;
ashleymills 0:714293de3836 5149
ashleymills 0:714293de3836 5150 /* get serial number */
ashleymills 0:714293de3836 5151 b = buff[*idx];
ashleymills 0:714293de3836 5152 *idx += 1;
ashleymills 0:714293de3836 5153
ashleymills 0:714293de3836 5154 if (b != ASN_INTEGER) {
ashleymills 0:714293de3836 5155 CYASSL_MSG("Expecting Integer");
ashleymills 0:714293de3836 5156 return ASN_PARSE_E;
ashleymills 0:714293de3836 5157 }
ashleymills 0:714293de3836 5158
ashleymills 0:714293de3836 5159 if (GetLength(buff, idx, &len, maxIdx) < 0)
ashleymills 0:714293de3836 5160 return ASN_PARSE_E;
ashleymills 0:714293de3836 5161
ashleymills 0:714293de3836 5162 if (len > EXTERNAL_SERIAL_SIZE) {
ashleymills 0:714293de3836 5163 CYASSL_MSG("Serial Size too big");
ashleymills 0:714293de3836 5164 return ASN_PARSE_E;
ashleymills 0:714293de3836 5165 }
ashleymills 0:714293de3836 5166
ashleymills 0:714293de3836 5167 rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), NULL, DYNAMIC_TYPE_CRL);
ashleymills 0:714293de3836 5168 if (rc == NULL) {
ashleymills 0:714293de3836 5169 CYASSL_MSG("Alloc Revoked Cert failed");
ashleymills 0:714293de3836 5170 return MEMORY_E;
ashleymills 0:714293de3836 5171 }
ashleymills 0:714293de3836 5172
ashleymills 0:714293de3836 5173 XMEMCPY(rc->serialNumber, &buff[*idx], len);
ashleymills 0:714293de3836 5174 rc->serialSz = len;
ashleymills 0:714293de3836 5175
ashleymills 0:714293de3836 5176 /* add to list */
ashleymills 0:714293de3836 5177 rc->next = dcrl->certs;
ashleymills 0:714293de3836 5178 dcrl->certs = rc;
ashleymills 0:714293de3836 5179 dcrl->totalCerts++;
ashleymills 0:714293de3836 5180
ashleymills 0:714293de3836 5181 *idx += len;
ashleymills 0:714293de3836 5182
ashleymills 0:714293de3836 5183 /* get date */
ashleymills 0:714293de3836 5184 b = buff[*idx];
ashleymills 0:714293de3836 5185 *idx += 1;
ashleymills 0:714293de3836 5186
ashleymills 0:714293de3836 5187 if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) {
ashleymills 0:714293de3836 5188 CYASSL_MSG("Expecting Date");
ashleymills 0:714293de3836 5189 return ASN_PARSE_E;
ashleymills 0:714293de3836 5190 }
ashleymills 0:714293de3836 5191
ashleymills 0:714293de3836 5192 if (GetLength(buff, idx, &len, maxIdx) < 0)
ashleymills 0:714293de3836 5193 return ASN_PARSE_E;
ashleymills 0:714293de3836 5194
ashleymills 0:714293de3836 5195 /* skip for now */
ashleymills 0:714293de3836 5196 *idx += len;
ashleymills 0:714293de3836 5197
ashleymills 0:714293de3836 5198 if (*idx != end) /* skip extensions */
ashleymills 0:714293de3836 5199 *idx = end;
ashleymills 0:714293de3836 5200
ashleymills 0:714293de3836 5201 return 0;
ashleymills 0:714293de3836 5202 }
ashleymills 0:714293de3836 5203
ashleymills 0:714293de3836 5204
ashleymills 0:714293de3836 5205 /* Get CRL Signature, 0 on success */
ashleymills 0:714293de3836 5206 static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
ashleymills 0:714293de3836 5207 int maxIdx)
ashleymills 0:714293de3836 5208 {
ashleymills 0:714293de3836 5209 int length;
ashleymills 0:714293de3836 5210 byte b;
ashleymills 0:714293de3836 5211
ashleymills 0:714293de3836 5212 CYASSL_ENTER("GetCRL_Signature");
ashleymills 0:714293de3836 5213
ashleymills 0:714293de3836 5214 b = source[*idx];
ashleymills 0:714293de3836 5215 *idx += 1;
ashleymills 0:714293de3836 5216 if (b != ASN_BIT_STRING)
ashleymills 0:714293de3836 5217 return ASN_BITSTR_E;
ashleymills 0:714293de3836 5218
ashleymills 0:714293de3836 5219 if (GetLength(source, idx, &length, maxIdx) < 0)
ashleymills 0:714293de3836 5220 return ASN_PARSE_E;
ashleymills 0:714293de3836 5221
ashleymills 0:714293de3836 5222 dcrl->sigLength = length;
ashleymills 0:714293de3836 5223
ashleymills 0:714293de3836 5224 b = source[*idx];
ashleymills 0:714293de3836 5225 *idx += 1;
ashleymills 0:714293de3836 5226 if (b != 0x00)
ashleymills 0:714293de3836 5227 return ASN_EXPECT_0_E;
ashleymills 0:714293de3836 5228
ashleymills 0:714293de3836 5229 dcrl->sigLength--;
ashleymills 0:714293de3836 5230 dcrl->signature = (byte*)&source[*idx];
ashleymills 0:714293de3836 5231
ashleymills 0:714293de3836 5232 *idx += dcrl->sigLength;
ashleymills 0:714293de3836 5233
ashleymills 0:714293de3836 5234 return 0;
ashleymills 0:714293de3836 5235 }
ashleymills 0:714293de3836 5236
ashleymills 0:714293de3836 5237
ashleymills 0:714293de3836 5238 /* prase crl buffer into decoded state, 0 on success */
ashleymills 0:714293de3836 5239 int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
ashleymills 0:714293de3836 5240 {
ashleymills 0:714293de3836 5241 int version, len;
ashleymills 0:714293de3836 5242 word32 oid, idx = 0;
ashleymills 0:714293de3836 5243 Signer* ca = NULL;
ashleymills 0:714293de3836 5244
ashleymills 0:714293de3836 5245 CYASSL_MSG("ParseCRL");
ashleymills 0:714293de3836 5246
ashleymills 0:714293de3836 5247 /* raw crl hash */
ashleymills 0:714293de3836 5248 /* hash here if needed for optimized comparisons
ashleymills 0:714293de3836 5249 * Sha sha;
ashleymills 0:714293de3836 5250 * InitSha(&sha);
ashleymills 0:714293de3836 5251 * ShaUpdate(&sha, buff, sz);
ashleymills 0:714293de3836 5252 * ShaFinal(&sha, dcrl->crlHash); */
ashleymills 0:714293de3836 5253
ashleymills 0:714293de3836 5254 if (GetSequence(buff, &idx, &len, sz) < 0)
ashleymills 0:714293de3836 5255 return ASN_PARSE_E;
ashleymills 0:714293de3836 5256
ashleymills 0:714293de3836 5257 dcrl->certBegin = idx;
ashleymills 0:714293de3836 5258
ashleymills 0:714293de3836 5259 if (GetSequence(buff, &idx, &len, sz) < 0)
ashleymills 0:714293de3836 5260 return ASN_PARSE_E;
ashleymills 0:714293de3836 5261 dcrl->sigIndex = len + idx;
ashleymills 0:714293de3836 5262
ashleymills 0:714293de3836 5263 /* may have version */
ashleymills 0:714293de3836 5264 if (buff[idx] == ASN_INTEGER) {
ashleymills 0:714293de3836 5265 if (GetMyVersion(buff, &idx, &version) < 0)
ashleymills 0:714293de3836 5266 return ASN_PARSE_E;
ashleymills 0:714293de3836 5267 }
ashleymills 0:714293de3836 5268
ashleymills 0:714293de3836 5269 if (GetAlgoId(buff, &idx, &oid, sz) < 0)
ashleymills 0:714293de3836 5270 return ASN_PARSE_E;
ashleymills 0:714293de3836 5271
ashleymills 0:714293de3836 5272 if (GetNameHash(buff, &idx, dcrl->issuerHash, sz) < 0)
ashleymills 0:714293de3836 5273 return ASN_PARSE_E;
ashleymills 0:714293de3836 5274
ashleymills 0:714293de3836 5275 if (GetBasicDate(buff, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
ashleymills 0:714293de3836 5276 return ASN_PARSE_E;
ashleymills 0:714293de3836 5277
ashleymills 0:714293de3836 5278 if (GetBasicDate(buff, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
ashleymills 0:714293de3836 5279 return ASN_PARSE_E;
ashleymills 0:714293de3836 5280
ashleymills 0:714293de3836 5281 if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
ashleymills 0:714293de3836 5282 CYASSL_MSG("CRL after date is no longer valid");
ashleymills 0:714293de3836 5283 return ASN_AFTER_DATE_E;
ashleymills 0:714293de3836 5284 }
ashleymills 0:714293de3836 5285
ashleymills 0:714293de3836 5286 if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) {
ashleymills 0:714293de3836 5287 if (GetSequence(buff, &idx, &len, sz) < 0)
ashleymills 0:714293de3836 5288 return ASN_PARSE_E;
ashleymills 0:714293de3836 5289
ashleymills 0:714293de3836 5290 len += idx;
ashleymills 0:714293de3836 5291
ashleymills 0:714293de3836 5292 while (idx < (word32)len) {
ashleymills 0:714293de3836 5293 if (GetRevoked(buff, &idx, dcrl, sz) < 0)
ashleymills 0:714293de3836 5294 return ASN_PARSE_E;
ashleymills 0:714293de3836 5295 }
ashleymills 0:714293de3836 5296 }
ashleymills 0:714293de3836 5297
ashleymills 0:714293de3836 5298 if (idx != dcrl->sigIndex)
ashleymills 0:714293de3836 5299 idx = dcrl->sigIndex; /* skip extensions */
ashleymills 0:714293de3836 5300
ashleymills 0:714293de3836 5301 if (GetAlgoId(buff, &idx, &dcrl->signatureOID, sz) < 0)
ashleymills 0:714293de3836 5302 return ASN_PARSE_E;
ashleymills 0:714293de3836 5303
ashleymills 0:714293de3836 5304 if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
ashleymills 0:714293de3836 5305 return ASN_PARSE_E;
ashleymills 0:714293de3836 5306
ashleymills 0:714293de3836 5307 /* openssl doesn't add skid by default for CRLs cause firefox chokes
ashleymills 0:714293de3836 5308 we're not assuming it's available yet */
ashleymills 0:714293de3836 5309 #if !defined(NO_SKID) && defined(CRL_SKID_READY)
ashleymills 0:714293de3836 5310 if (dcrl->extAuthKeyIdSet)
ashleymills 0:714293de3836 5311 ca = GetCA(cm, dcrl->extAuthKeyId);
ashleymills 0:714293de3836 5312 if (ca == NULL)
ashleymills 0:714293de3836 5313 ca = GetCAByName(cm, dcrl->issuerHash);
ashleymills 0:714293de3836 5314 #else /* NO_SKID */
ashleymills 0:714293de3836 5315 ca = GetCA(cm, dcrl->issuerHash);
ashleymills 0:714293de3836 5316 #endif /* NO_SKID */
ashleymills 0:714293de3836 5317 CYASSL_MSG("About to verify CRL signature");
ashleymills 0:714293de3836 5318
ashleymills 0:714293de3836 5319 if (ca) {
ashleymills 0:714293de3836 5320 CYASSL_MSG("Found CRL issuer CA");
ashleymills 0:714293de3836 5321 /* try to confirm/verify signature */
ashleymills 0:714293de3836 5322 if (!ConfirmSignature(buff + dcrl->certBegin,
ashleymills 0:714293de3836 5323 dcrl->sigIndex - dcrl->certBegin,
ashleymills 0:714293de3836 5324 ca->publicKey, ca->pubKeySize, ca->keyOID,
ashleymills 0:714293de3836 5325 dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) {
ashleymills 0:714293de3836 5326 CYASSL_MSG("CRL Confirm signature failed");
ashleymills 0:714293de3836 5327 return ASN_CRL_CONFIRM_E;
ashleymills 0:714293de3836 5328 }
ashleymills 0:714293de3836 5329 }
ashleymills 0:714293de3836 5330 else {
ashleymills 0:714293de3836 5331 CYASSL_MSG("Did NOT find CRL issuer CA");
ashleymills 0:714293de3836 5332 return ASN_CRL_NO_SIGNER_E;
ashleymills 0:714293de3836 5333 }
ashleymills 0:714293de3836 5334
ashleymills 0:714293de3836 5335 return 0;
ashleymills 0:714293de3836 5336 }
ashleymills 0:714293de3836 5337
ashleymills 0:714293de3836 5338 #endif /* HAVE_CRL */
ashleymills 0:714293de3836 5339 #endif
ashleymills 0:714293de3836 5340