cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

Committer:
ashleymills
Date:
Fri Apr 26 16:59:36 2013 +0000
Revision:
1:b211d97b0068
Parent:
0:e979170e02e7
nothing

Who changed what in which revision?

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