cya_u
Fork of CyaSSL-forEncrypt by
asn.c@2:d0516dc143b1, 2017-05-10 (annotated)
- Committer:
- vbahl2
- Date:
- Wed May 10 18:20:47 2017 +0000
- Revision:
- 2:d0516dc143b1
- Parent:
- 0:5045d2638c29
updated
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
toddouska | 0:5045d2638c29 | 1 | /* asn.c |
toddouska | 0:5045d2638c29 | 2 | * |
toddouska | 0:5045d2638c29 | 3 | * Copyright (C) 2006-2009 Sawtooth Consulting Ltd. |
toddouska | 0:5045d2638c29 | 4 | * |
toddouska | 0:5045d2638c29 | 5 | * This file is part of CyaSSL. |
toddouska | 0:5045d2638c29 | 6 | * |
toddouska | 0:5045d2638c29 | 7 | * CyaSSL is free software; you can redistribute it and/or modify |
toddouska | 0:5045d2638c29 | 8 | * it under the terms of the GNU General Public License as published by |
toddouska | 0:5045d2638c29 | 9 | * the Free Software Foundation; either version 2 of the License, or |
toddouska | 0:5045d2638c29 | 10 | * (at your option) any later version. |
toddouska | 0:5045d2638c29 | 11 | * |
toddouska | 0:5045d2638c29 | 12 | * CyaSSL is distributed in the hope that it will be useful, |
toddouska | 0:5045d2638c29 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
toddouska | 0:5045d2638c29 | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
toddouska | 0:5045d2638c29 | 15 | * GNU General Public License for more details. |
toddouska | 0:5045d2638c29 | 16 | * |
toddouska | 0:5045d2638c29 | 17 | * You should have received a copy of the GNU General Public License |
toddouska | 0:5045d2638c29 | 18 | * along with this program; if not, write to the Free Software |
toddouska | 0:5045d2638c29 | 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
toddouska | 0:5045d2638c29 | 20 | */ |
toddouska | 0:5045d2638c29 | 21 | |
toddouska | 0:5045d2638c29 | 22 | |
toddouska | 0:5045d2638c29 | 23 | #ifdef THREADX |
toddouska | 0:5045d2638c29 | 24 | #include "os.h" /* dc_rtc_api needs */ |
toddouska | 0:5045d2638c29 | 25 | #include "dc_rtc_api.h" /* to get current time */ |
toddouska | 0:5045d2638c29 | 26 | #endif |
toddouska | 0:5045d2638c29 | 27 | #include "asn.h" |
toddouska | 0:5045d2638c29 | 28 | #include "coding.h" |
toddouska | 0:5045d2638c29 | 29 | #include "ctc_sha.h" |
toddouska | 0:5045d2638c29 | 30 | #include "ctc_md5.h" |
toddouska | 0:5045d2638c29 | 31 | #include "error.h" |
toddouska | 0:5045d2638c29 | 32 | |
toddouska | 0:5045d2638c29 | 33 | #ifdef HAVE_NTRU |
toddouska | 0:5045d2638c29 | 34 | #include "crypto_ntru.h" |
toddouska | 0:5045d2638c29 | 35 | #endif |
toddouska | 0:5045d2638c29 | 36 | |
toddouska | 0:5045d2638c29 | 37 | |
toddouska | 0:5045d2638c29 | 38 | #ifdef _MSC_VER |
toddouska | 0:5045d2638c29 | 39 | /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */ |
toddouska | 0:5045d2638c29 | 40 | #pragma warning(disable: 4996) |
toddouska | 0:5045d2638c29 | 41 | #endif |
toddouska | 0:5045d2638c29 | 42 | |
toddouska | 0:5045d2638c29 | 43 | |
toddouska | 0:5045d2638c29 | 44 | #ifndef TRUE |
toddouska | 0:5045d2638c29 | 45 | enum { |
toddouska | 0:5045d2638c29 | 46 | FALSE = 0, |
toddouska | 0:5045d2638c29 | 47 | TRUE = 1 |
toddouska | 0:5045d2638c29 | 48 | }; |
toddouska | 0:5045d2638c29 | 49 | #endif |
toddouska | 0:5045d2638c29 | 50 | |
toddouska | 0:5045d2638c29 | 51 | enum { |
toddouska | 0:5045d2638c29 | 52 | ISSUER = 0, |
toddouska | 0:5045d2638c29 | 53 | SUBJECT = 1, |
toddouska | 0:5045d2638c29 | 54 | |
toddouska | 0:5045d2638c29 | 55 | BEFORE = 0, |
toddouska | 0:5045d2638c29 | 56 | AFTER = 1 |
toddouska | 0:5045d2638c29 | 57 | }; |
toddouska | 0:5045d2638c29 | 58 | |
toddouska | 0:5045d2638c29 | 59 | |
toddouska | 0:5045d2638c29 | 60 | #ifdef THREADX |
toddouska | 0:5045d2638c29 | 61 | /* uses parital <time.h> structures */ |
toddouska | 0:5045d2638c29 | 62 | #define XTIME(tl) (0) |
toddouska | 0:5045d2638c29 | 63 | #define XGMTIME(c) my_gmtime((c)) |
toddouska | 0:5045d2638c29 | 64 | #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) |
toddouska | 0:5045d2638c29 | 65 | #elif defined(MICRIUM) |
toddouska | 0:5045d2638c29 | 66 | #include <clk.h> |
toddouska | 0:5045d2638c29 | 67 | #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) |
toddouska | 0:5045d2638c29 | 68 | #define XVALIDATE_DATE(d, f, t) NetSecure_ValidDate((d), (f), (t)) |
toddouska | 0:5045d2638c29 | 69 | #else |
toddouska | 0:5045d2638c29 | 70 | #define XVALIDATE_DATE(d, f, t) (0) |
toddouska | 0:5045d2638c29 | 71 | #endif |
toddouska | 0:5045d2638c29 | 72 | #define NO_TIME_H |
toddouska | 0:5045d2638c29 | 73 | /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */ |
toddouska | 0:5045d2638c29 | 74 | #elif defined(USER_TIME) |
toddouska | 0:5045d2638c29 | 75 | /* no <time.h> strucutres used */ |
toddouska | 0:5045d2638c29 | 76 | #define NO_TIME_H |
toddouska | 0:5045d2638c29 | 77 | /* user time, and gmtime compatible functions, there is a gmtime |
toddouska | 0:5045d2638c29 | 78 | implementation here that WINCE uses, so really just need some ticks |
toddouska | 0:5045d2638c29 | 79 | since the EPOCH |
toddouska | 0:5045d2638c29 | 80 | */ |
toddouska | 0:5045d2638c29 | 81 | #else |
toddouska | 0:5045d2638c29 | 82 | /* default */ |
toddouska | 0:5045d2638c29 | 83 | /* uses complete <time.h> facility */ |
toddouska | 0:5045d2638c29 | 84 | #include <time.h> |
toddouska | 0:5045d2638c29 | 85 | #define XTIME(tl) time((tl)) |
toddouska | 0:5045d2638c29 | 86 | #define XGMTIME(c) gmtime((c)) |
toddouska | 0:5045d2638c29 | 87 | #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) |
toddouska | 0:5045d2638c29 | 88 | #endif |
toddouska | 0:5045d2638c29 | 89 | |
toddouska | 0:5045d2638c29 | 90 | |
toddouska | 0:5045d2638c29 | 91 | #ifdef _WIN32_WCE |
toddouska | 0:5045d2638c29 | 92 | /* no time() or gmtime() even though in time.h header?? */ |
toddouska | 0:5045d2638c29 | 93 | |
toddouska | 0:5045d2638c29 | 94 | #include <windows.h> |
toddouska | 0:5045d2638c29 | 95 | |
toddouska | 0:5045d2638c29 | 96 | |
toddouska | 0:5045d2638c29 | 97 | time_t time(time_t* timer) |
toddouska | 0:5045d2638c29 | 98 | { |
toddouska | 0:5045d2638c29 | 99 | SYSTEMTIME sysTime; |
toddouska | 0:5045d2638c29 | 100 | FILETIME fTime; |
toddouska | 0:5045d2638c29 | 101 | ULARGE_INTEGER intTime; |
toddouska | 0:5045d2638c29 | 102 | time_t localTime; |
toddouska | 0:5045d2638c29 | 103 | |
toddouska | 0:5045d2638c29 | 104 | if (timer == NULL) |
toddouska | 0:5045d2638c29 | 105 | timer = &localTime; |
toddouska | 0:5045d2638c29 | 106 | |
toddouska | 0:5045d2638c29 | 107 | GetSystemTime(&sysTime); |
toddouska | 0:5045d2638c29 | 108 | SystemTimeToFileTime(&sysTime, &fTime); |
toddouska | 0:5045d2638c29 | 109 | |
toddouska | 0:5045d2638c29 | 110 | XMEMCPY(&intTime, &fTime, sizeof(FILETIME)); |
toddouska | 0:5045d2638c29 | 111 | /* subtract EPOCH */ |
toddouska | 0:5045d2638c29 | 112 | intTime.QuadPart -= 0x19db1ded53e8000; |
toddouska | 0:5045d2638c29 | 113 | /* to secs */ |
toddouska | 0:5045d2638c29 | 114 | intTime.QuadPart /= 10000000; |
toddouska | 0:5045d2638c29 | 115 | *timer = (time_t)intTime.QuadPart; |
toddouska | 0:5045d2638c29 | 116 | |
toddouska | 0:5045d2638c29 | 117 | return *timer; |
toddouska | 0:5045d2638c29 | 118 | } |
toddouska | 0:5045d2638c29 | 119 | |
toddouska | 0:5045d2638c29 | 120 | |
toddouska | 0:5045d2638c29 | 121 | |
toddouska | 0:5045d2638c29 | 122 | struct tm* gmtime(const time_t* timer) |
toddouska | 0:5045d2638c29 | 123 | { |
toddouska | 0:5045d2638c29 | 124 | #define YEAR0 1900 |
toddouska | 0:5045d2638c29 | 125 | #define EPOCH_YEAR 1970 |
toddouska | 0:5045d2638c29 | 126 | #define SECS_DAY (24L * 60L * 60L) |
toddouska | 0:5045d2638c29 | 127 | #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400))) |
toddouska | 0:5045d2638c29 | 128 | #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365) |
toddouska | 0:5045d2638c29 | 129 | |
toddouska | 0:5045d2638c29 | 130 | static const int _ytab[2][12] = |
toddouska | 0:5045d2638c29 | 131 | { |
toddouska | 0:5045d2638c29 | 132 | {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, |
toddouska | 0:5045d2638c29 | 133 | {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} |
toddouska | 0:5045d2638c29 | 134 | }; |
toddouska | 0:5045d2638c29 | 135 | |
toddouska | 0:5045d2638c29 | 136 | static struct tm st_time; |
toddouska | 0:5045d2638c29 | 137 | struct tm* ret = &st_time; |
toddouska | 0:5045d2638c29 | 138 | time_t time = *timer; |
toddouska | 0:5045d2638c29 | 139 | unsigned long dayclock, dayno; |
toddouska | 0:5045d2638c29 | 140 | int year = EPOCH_YEAR; |
toddouska | 0:5045d2638c29 | 141 | |
toddouska | 0:5045d2638c29 | 142 | dayclock = (unsigned long)time % SECS_DAY; |
toddouska | 0:5045d2638c29 | 143 | dayno = (unsigned long)time / SECS_DAY; |
toddouska | 0:5045d2638c29 | 144 | |
toddouska | 0:5045d2638c29 | 145 | ret->tm_sec = dayclock % 60; |
toddouska | 0:5045d2638c29 | 146 | ret->tm_min = (dayclock % 3600) / 60; |
toddouska | 0:5045d2638c29 | 147 | ret->tm_hour = dayclock / 3600; |
toddouska | 0:5045d2638c29 | 148 | ret->tm_wday = (dayno + 4) % 7; /* day 0 a Thursday */ |
toddouska | 0:5045d2638c29 | 149 | |
toddouska | 0:5045d2638c29 | 150 | while(dayno >= (unsigned long)YEARSIZE(year)) { |
toddouska | 0:5045d2638c29 | 151 | dayno -= YEARSIZE(year); |
toddouska | 0:5045d2638c29 | 152 | year++; |
toddouska | 0:5045d2638c29 | 153 | } |
toddouska | 0:5045d2638c29 | 154 | |
toddouska | 0:5045d2638c29 | 155 | ret->tm_year = year - YEAR0; |
toddouska | 0:5045d2638c29 | 156 | ret->tm_yday = dayno; |
toddouska | 0:5045d2638c29 | 157 | ret->tm_mon = 0; |
toddouska | 0:5045d2638c29 | 158 | |
toddouska | 0:5045d2638c29 | 159 | while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) { |
toddouska | 0:5045d2638c29 | 160 | dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon]; |
toddouska | 0:5045d2638c29 | 161 | ret->tm_mon++; |
toddouska | 0:5045d2638c29 | 162 | } |
toddouska | 0:5045d2638c29 | 163 | |
toddouska | 0:5045d2638c29 | 164 | ret->tm_mday = ++dayno; |
toddouska | 0:5045d2638c29 | 165 | ret->tm_isdst = 0; |
toddouska | 0:5045d2638c29 | 166 | |
toddouska | 0:5045d2638c29 | 167 | return ret; |
toddouska | 0:5045d2638c29 | 168 | } |
toddouska | 0:5045d2638c29 | 169 | |
toddouska | 0:5045d2638c29 | 170 | #endif /* _WIN32_WCE */ |
toddouska | 0:5045d2638c29 | 171 | |
toddouska | 0:5045d2638c29 | 172 | |
toddouska | 0:5045d2638c29 | 173 | |
toddouska | 0:5045d2638c29 | 174 | #ifdef THREADX |
toddouska | 0:5045d2638c29 | 175 | |
toddouska | 0:5045d2638c29 | 176 | #define YEAR0 1900 |
toddouska | 0:5045d2638c29 | 177 | |
toddouska | 0:5045d2638c29 | 178 | struct tm* my_gmtime(const time_t* timer) /* has a gmtime() but hangs */ |
toddouska | 0:5045d2638c29 | 179 | { |
toddouska | 0:5045d2638c29 | 180 | static struct tm st_time; |
toddouska | 0:5045d2638c29 | 181 | struct tm* ret = &st_time; |
toddouska | 0:5045d2638c29 | 182 | |
toddouska | 0:5045d2638c29 | 183 | DC_RTC_CALENDAR cal; |
toddouska | 0:5045d2638c29 | 184 | dc_rtc_time_get(&cal, TRUE); |
toddouska | 0:5045d2638c29 | 185 | |
toddouska | 0:5045d2638c29 | 186 | ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */ |
toddouska | 0:5045d2638c29 | 187 | ret->tm_mon = cal.month - 1; /* gm starts at 0 */ |
toddouska | 0:5045d2638c29 | 188 | ret->tm_mday = cal.day; |
toddouska | 0:5045d2638c29 | 189 | ret->tm_hour = cal.hour; |
toddouska | 0:5045d2638c29 | 190 | ret->tm_min = cal.minute; |
toddouska | 0:5045d2638c29 | 191 | ret->tm_sec = cal.second; |
toddouska | 0:5045d2638c29 | 192 | |
toddouska | 0:5045d2638c29 | 193 | return ret; |
toddouska | 0:5045d2638c29 | 194 | } |
toddouska | 0:5045d2638c29 | 195 | |
toddouska | 0:5045d2638c29 | 196 | #endif /* THREADX */ |
toddouska | 0:5045d2638c29 | 197 | |
toddouska | 0:5045d2638c29 | 198 | |
toddouska | 0:5045d2638c29 | 199 | static INLINE word32 btoi(byte b) |
toddouska | 0:5045d2638c29 | 200 | { |
toddouska | 0:5045d2638c29 | 201 | return b - 0x30; |
toddouska | 0:5045d2638c29 | 202 | } |
toddouska | 0:5045d2638c29 | 203 | |
toddouska | 0:5045d2638c29 | 204 | |
toddouska | 0:5045d2638c29 | 205 | /* two byte date/time, add to value */ |
toddouska | 0:5045d2638c29 | 206 | static INLINE void GetTime(int* value, const byte* date, int* idx) |
toddouska | 0:5045d2638c29 | 207 | { |
toddouska | 0:5045d2638c29 | 208 | int i = *idx; |
toddouska | 0:5045d2638c29 | 209 | |
toddouska | 0:5045d2638c29 | 210 | *value += btoi(date[i++]) * 10; |
toddouska | 0:5045d2638c29 | 211 | *value += btoi(date[i++]); |
toddouska | 0:5045d2638c29 | 212 | |
toddouska | 0:5045d2638c29 | 213 | *idx = i; |
toddouska | 0:5045d2638c29 | 214 | } |
toddouska | 0:5045d2638c29 | 215 | |
toddouska | 0:5045d2638c29 | 216 | |
toddouska | 0:5045d2638c29 | 217 | #if defined(MICRIUM) |
toddouska | 0:5045d2638c29 | 218 | |
toddouska | 0:5045d2638c29 | 219 | static int NetSecure_ValidDate(CPU_INT08U *date, CPU_INT08U format, |
toddouska | 0:5045d2638c29 | 220 | CPU_INT08U dateType) |
toddouska | 0:5045d2638c29 | 221 | { |
toddouska | 0:5045d2638c29 | 222 | CLK_DATE_TIME cert_date_time; |
toddouska | 0:5045d2638c29 | 223 | CLK_TS_SEC cert_ts_sec; |
toddouska | 0:5045d2638c29 | 224 | CLK_TS_SEC local_ts_sec; |
toddouska | 0:5045d2638c29 | 225 | CPU_INT32S i; |
toddouska | 0:5045d2638c29 | 226 | CPU_INT32S val; |
toddouska | 0:5045d2638c29 | 227 | |
toddouska | 0:5045d2638c29 | 228 | local_ts_sec = Clk_GetTS(); |
toddouska | 0:5045d2638c29 | 229 | XMEMSET(&cert_date_time, 0, sizeof(cert_date_time)); |
toddouska | 0:5045d2638c29 | 230 | |
toddouska | 0:5045d2638c29 | 231 | i = 0; |
toddouska | 0:5045d2638c29 | 232 | if (format == ASN_UTC_TIME) { |
toddouska | 0:5045d2638c29 | 233 | if (btoi(date[0]) >= 5) |
toddouska | 0:5045d2638c29 | 234 | cert_date_time.Yr = 1900; |
toddouska | 0:5045d2638c29 | 235 | else |
toddouska | 0:5045d2638c29 | 236 | cert_date_time.Yr = 2000; |
toddouska | 0:5045d2638c29 | 237 | } |
toddouska | 0:5045d2638c29 | 238 | else { /* format == GENERALIZED_TIME */ |
toddouska | 0:5045d2638c29 | 239 | cert_date_time.Yr += btoi(date[i++]) * 1000; |
toddouska | 0:5045d2638c29 | 240 | cert_date_time.Yr += btoi(date[i++]) * 100; |
toddouska | 0:5045d2638c29 | 241 | } |
toddouska | 0:5045d2638c29 | 242 | |
toddouska | 0:5045d2638c29 | 243 | val = cert_date_time.Yr; |
toddouska | 0:5045d2638c29 | 244 | GetTime(&val, date, &i); |
toddouska | 0:5045d2638c29 | 245 | cert_date_time.Yr = (CLK_YR)val; |
toddouska | 0:5045d2638c29 | 246 | |
toddouska | 0:5045d2638c29 | 247 | val = 0; |
toddouska | 0:5045d2638c29 | 248 | GetTime(&val, date, &i); |
toddouska | 0:5045d2638c29 | 249 | cert_date_time.Month = (CLK_MONTH)val; |
toddouska | 0:5045d2638c29 | 250 | |
toddouska | 0:5045d2638c29 | 251 | val = 0; |
toddouska | 0:5045d2638c29 | 252 | GetTime(&val, date, &i); |
toddouska | 0:5045d2638c29 | 253 | cert_date_time.Day = (CLK_DAY)val; |
toddouska | 0:5045d2638c29 | 254 | |
toddouska | 0:5045d2638c29 | 255 | val = 0; |
toddouska | 0:5045d2638c29 | 256 | GetTime(&val, date, &i); |
toddouska | 0:5045d2638c29 | 257 | cert_date_time.Hr = (CLK_HR)val; |
toddouska | 0:5045d2638c29 | 258 | |
toddouska | 0:5045d2638c29 | 259 | val = 0; |
toddouska | 0:5045d2638c29 | 260 | GetTime(&val, date, &i); |
toddouska | 0:5045d2638c29 | 261 | cert_date_time.Min = (CLK_MIN)val; |
toddouska | 0:5045d2638c29 | 262 | |
toddouska | 0:5045d2638c29 | 263 | val = 0; |
toddouska | 0:5045d2638c29 | 264 | GetTime(&val, date, &i); |
toddouska | 0:5045d2638c29 | 265 | cert_date_time.Sec = (CLK_SEC)val; |
toddouska | 0:5045d2638c29 | 266 | |
toddouska | 0:5045d2638c29 | 267 | if (date[i] != 'Z') /* only Zulu supported for this profile */ |
toddouska | 0:5045d2638c29 | 268 | return 0; |
toddouska | 0:5045d2638c29 | 269 | |
toddouska | 0:5045d2638c29 | 270 | cert_date_time.DayOfWk = 1; |
toddouska | 0:5045d2638c29 | 271 | cert_date_time.DayOfYr = 1; |
toddouska | 0:5045d2638c29 | 272 | Clk_DateTimeToTS(&cert_ts_sec, &cert_date_time); |
toddouska | 0:5045d2638c29 | 273 | |
toddouska | 0:5045d2638c29 | 274 | |
toddouska | 0:5045d2638c29 | 275 | if (dateType == BEFORE) { |
toddouska | 0:5045d2638c29 | 276 | if (local_ts_sec < cert_ts_sec) /* If cert creation date after |
toddouska | 0:5045d2638c29 | 277 | current date... */ |
toddouska | 0:5045d2638c29 | 278 | return (DEF_FAIL); /* ... report an error. */ |
toddouska | 0:5045d2638c29 | 279 | } else { |
toddouska | 0:5045d2638c29 | 280 | if (local_ts_sec > cert_ts_sec) /* If cert expiration date before |
toddouska | 0:5045d2638c29 | 281 | current date... */ |
toddouska | 0:5045d2638c29 | 282 | return (DEF_FAIL); /* ... report an error. */ |
toddouska | 0:5045d2638c29 | 283 | } |
toddouska | 0:5045d2638c29 | 284 | |
toddouska | 0:5045d2638c29 | 285 | return (DEF_OK); |
toddouska | 0:5045d2638c29 | 286 | } |
toddouska | 0:5045d2638c29 | 287 | |
toddouska | 0:5045d2638c29 | 288 | #endif /* MICRIUM */ |
toddouska | 0:5045d2638c29 | 289 | |
toddouska | 0:5045d2638c29 | 290 | |
toddouska | 0:5045d2638c29 | 291 | int GetLength(const byte* input, word32* inOutIdx, int* len) |
toddouska | 0:5045d2638c29 | 292 | { |
toddouska | 0:5045d2638c29 | 293 | int length = 0; |
toddouska | 0:5045d2638c29 | 294 | word32 i = *inOutIdx; |
toddouska | 0:5045d2638c29 | 295 | |
toddouska | 0:5045d2638c29 | 296 | byte b = input[i++]; |
toddouska | 0:5045d2638c29 | 297 | if (b >= ASN_LONG_LENGTH) { |
toddouska | 0:5045d2638c29 | 298 | word32 bytes = b & 0x7F; |
toddouska | 0:5045d2638c29 | 299 | |
toddouska | 0:5045d2638c29 | 300 | while (bytes--) { |
toddouska | 0:5045d2638c29 | 301 | b = input[i++]; |
toddouska | 0:5045d2638c29 | 302 | length = (length << 8) | b; |
toddouska | 0:5045d2638c29 | 303 | } |
toddouska | 0:5045d2638c29 | 304 | } |
toddouska | 0:5045d2638c29 | 305 | else |
toddouska | 0:5045d2638c29 | 306 | length = b; |
toddouska | 0:5045d2638c29 | 307 | |
toddouska | 0:5045d2638c29 | 308 | *inOutIdx = i; |
toddouska | 0:5045d2638c29 | 309 | *len = length; |
toddouska | 0:5045d2638c29 | 310 | |
toddouska | 0:5045d2638c29 | 311 | return length; |
toddouska | 0:5045d2638c29 | 312 | } |
toddouska | 0:5045d2638c29 | 313 | |
toddouska | 0:5045d2638c29 | 314 | |
toddouska | 0:5045d2638c29 | 315 | int GetSequence(const byte* input, word32* inOutIdx, int* len) |
toddouska | 0:5045d2638c29 | 316 | { |
toddouska | 0:5045d2638c29 | 317 | int length = -1; |
toddouska | 0:5045d2638c29 | 318 | word32 idx = *inOutIdx; |
toddouska | 0:5045d2638c29 | 319 | |
toddouska | 0:5045d2638c29 | 320 | if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) || |
toddouska | 0:5045d2638c29 | 321 | GetLength(input, &idx, &length) < 0) |
toddouska | 0:5045d2638c29 | 322 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 323 | |
toddouska | 0:5045d2638c29 | 324 | *len = length; |
toddouska | 0:5045d2638c29 | 325 | *inOutIdx = idx; |
toddouska | 0:5045d2638c29 | 326 | |
toddouska | 0:5045d2638c29 | 327 | return length; |
toddouska | 0:5045d2638c29 | 328 | } |
toddouska | 0:5045d2638c29 | 329 | |
toddouska | 0:5045d2638c29 | 330 | |
toddouska | 0:5045d2638c29 | 331 | int GetSet(const byte* input, word32* inOutIdx, int* len) |
toddouska | 0:5045d2638c29 | 332 | { |
toddouska | 0:5045d2638c29 | 333 | int length = -1; |
toddouska | 0:5045d2638c29 | 334 | word32 idx = *inOutIdx; |
toddouska | 0:5045d2638c29 | 335 | |
toddouska | 0:5045d2638c29 | 336 | if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) || |
toddouska | 0:5045d2638c29 | 337 | GetLength(input, &idx, &length) < 0) |
toddouska | 0:5045d2638c29 | 338 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 339 | |
toddouska | 0:5045d2638c29 | 340 | *len = length; |
toddouska | 0:5045d2638c29 | 341 | *inOutIdx = idx; |
toddouska | 0:5045d2638c29 | 342 | |
toddouska | 0:5045d2638c29 | 343 | return length; |
toddouska | 0:5045d2638c29 | 344 | } |
toddouska | 0:5045d2638c29 | 345 | |
toddouska | 0:5045d2638c29 | 346 | |
toddouska | 0:5045d2638c29 | 347 | /* winodws header clash for WinCE using GetVersion */ |
toddouska | 0:5045d2638c29 | 348 | int GetMyVersion(const byte* input, word32* inOutIdx, int* version) |
toddouska | 0:5045d2638c29 | 349 | { |
toddouska | 0:5045d2638c29 | 350 | word32 idx = *inOutIdx; |
toddouska | 0:5045d2638c29 | 351 | |
toddouska | 0:5045d2638c29 | 352 | if (input[idx++] != ASN_INTEGER) |
toddouska | 0:5045d2638c29 | 353 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 354 | |
toddouska | 0:5045d2638c29 | 355 | if (input[idx++] != 0x01) |
toddouska | 0:5045d2638c29 | 356 | return ASN_VERSION_E; |
toddouska | 0:5045d2638c29 | 357 | |
toddouska | 0:5045d2638c29 | 358 | *version = input[idx++]; |
toddouska | 0:5045d2638c29 | 359 | *inOutIdx = idx; |
toddouska | 0:5045d2638c29 | 360 | |
toddouska | 0:5045d2638c29 | 361 | return *version; |
toddouska | 0:5045d2638c29 | 362 | } |
toddouska | 0:5045d2638c29 | 363 | |
toddouska | 0:5045d2638c29 | 364 | |
toddouska | 0:5045d2638c29 | 365 | /* May not have one, not an error */ |
toddouska | 0:5045d2638c29 | 366 | int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version) |
toddouska | 0:5045d2638c29 | 367 | { |
toddouska | 0:5045d2638c29 | 368 | word32 idx = *inOutIdx; |
toddouska | 0:5045d2638c29 | 369 | |
toddouska | 0:5045d2638c29 | 370 | if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { |
toddouska | 0:5045d2638c29 | 371 | *inOutIdx = ++idx; /* eat header */ |
toddouska | 0:5045d2638c29 | 372 | return GetMyVersion(input, inOutIdx, version); |
toddouska | 0:5045d2638c29 | 373 | } |
toddouska | 0:5045d2638c29 | 374 | |
toddouska | 0:5045d2638c29 | 375 | /* go back as is */ |
toddouska | 0:5045d2638c29 | 376 | *version = 0; |
toddouska | 0:5045d2638c29 | 377 | |
toddouska | 0:5045d2638c29 | 378 | return 0; |
toddouska | 0:5045d2638c29 | 379 | } |
toddouska | 0:5045d2638c29 | 380 | |
toddouska | 0:5045d2638c29 | 381 | |
toddouska | 0:5045d2638c29 | 382 | int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx ) |
toddouska | 0:5045d2638c29 | 383 | { |
toddouska | 0:5045d2638c29 | 384 | word32 i = *inOutIdx; |
toddouska | 0:5045d2638c29 | 385 | byte b = input[i++]; |
toddouska | 0:5045d2638c29 | 386 | int length; |
toddouska | 0:5045d2638c29 | 387 | |
toddouska | 0:5045d2638c29 | 388 | if (b != ASN_INTEGER) |
toddouska | 0:5045d2638c29 | 389 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 390 | |
toddouska | 0:5045d2638c29 | 391 | if (GetLength(input, &i, &length) < 0) |
toddouska | 0:5045d2638c29 | 392 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 393 | |
toddouska | 0:5045d2638c29 | 394 | if ( (b = input[i++]) == 0x00) |
toddouska | 0:5045d2638c29 | 395 | length--; |
toddouska | 0:5045d2638c29 | 396 | else |
toddouska | 0:5045d2638c29 | 397 | i--; |
toddouska | 0:5045d2638c29 | 398 | |
toddouska | 0:5045d2638c29 | 399 | mp_init(mpi); |
toddouska | 0:5045d2638c29 | 400 | if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) { |
toddouska | 0:5045d2638c29 | 401 | mp_clear(mpi); |
toddouska | 0:5045d2638c29 | 402 | return ASN_GETINT_E; |
toddouska | 0:5045d2638c29 | 403 | } |
toddouska | 0:5045d2638c29 | 404 | |
toddouska | 0:5045d2638c29 | 405 | *inOutIdx = i + length; |
toddouska | 0:5045d2638c29 | 406 | return 0; |
toddouska | 0:5045d2638c29 | 407 | } |
toddouska | 0:5045d2638c29 | 408 | |
toddouska | 0:5045d2638c29 | 409 | |
toddouska | 0:5045d2638c29 | 410 | static int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid) |
toddouska | 0:5045d2638c29 | 411 | { |
toddouska | 0:5045d2638c29 | 412 | int length; |
toddouska | 0:5045d2638c29 | 413 | word32 i = *inOutIdx; |
toddouska | 0:5045d2638c29 | 414 | byte b; |
toddouska | 0:5045d2638c29 | 415 | *oid = 0; |
toddouska | 0:5045d2638c29 | 416 | |
toddouska | 0:5045d2638c29 | 417 | if (GetSequence(input, &i, &length) < 0) |
toddouska | 0:5045d2638c29 | 418 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 419 | |
toddouska | 0:5045d2638c29 | 420 | b = input[i++]; |
toddouska | 0:5045d2638c29 | 421 | if (b != ASN_OBJECT_ID) |
toddouska | 0:5045d2638c29 | 422 | return ASN_OBJECT_ID_E; |
toddouska | 0:5045d2638c29 | 423 | |
toddouska | 0:5045d2638c29 | 424 | if (GetLength(input, &i, &length) < 0) |
toddouska | 0:5045d2638c29 | 425 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 426 | |
toddouska | 0:5045d2638c29 | 427 | while(length--) |
toddouska | 0:5045d2638c29 | 428 | *oid += input[i++]; |
toddouska | 0:5045d2638c29 | 429 | /* just sum it up for now */ |
toddouska | 0:5045d2638c29 | 430 | |
toddouska | 0:5045d2638c29 | 431 | /* could have NULL tag and 0 terminator, but may not */ |
toddouska | 0:5045d2638c29 | 432 | b = input[i++]; |
toddouska | 0:5045d2638c29 | 433 | |
toddouska | 0:5045d2638c29 | 434 | if (b == ASN_TAG_NULL) { |
toddouska | 0:5045d2638c29 | 435 | b = input[i++]; |
toddouska | 0:5045d2638c29 | 436 | if (b != 0) |
toddouska | 0:5045d2638c29 | 437 | return ASN_EXPECT_0_E; |
toddouska | 0:5045d2638c29 | 438 | } |
toddouska | 0:5045d2638c29 | 439 | else |
toddouska | 0:5045d2638c29 | 440 | /* go back, didn't have it */ |
toddouska | 0:5045d2638c29 | 441 | i--; |
toddouska | 0:5045d2638c29 | 442 | |
toddouska | 0:5045d2638c29 | 443 | *inOutIdx = i; |
toddouska | 0:5045d2638c29 | 444 | |
toddouska | 0:5045d2638c29 | 445 | return 0; |
toddouska | 0:5045d2638c29 | 446 | } |
toddouska | 0:5045d2638c29 | 447 | |
toddouska | 0:5045d2638c29 | 448 | |
toddouska | 0:5045d2638c29 | 449 | int RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, |
toddouska | 0:5045d2638c29 | 450 | word32 inSz) |
toddouska | 0:5045d2638c29 | 451 | { |
toddouska | 0:5045d2638c29 | 452 | word32 begin = *inOutIdx; |
toddouska | 0:5045d2638c29 | 453 | int version, length; |
toddouska | 0:5045d2638c29 | 454 | |
toddouska | 0:5045d2638c29 | 455 | if (GetSequence(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 456 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 457 | |
toddouska | 0:5045d2638c29 | 458 | if ((word32)length > (inSz - (*inOutIdx - begin))) |
toddouska | 0:5045d2638c29 | 459 | return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 460 | |
toddouska | 0:5045d2638c29 | 461 | if (GetMyVersion(input, inOutIdx, &version) < 0) |
toddouska | 0:5045d2638c29 | 462 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 463 | |
toddouska | 0:5045d2638c29 | 464 | key->type = RSA_PRIVATE; |
toddouska | 0:5045d2638c29 | 465 | |
toddouska | 0:5045d2638c29 | 466 | if (GetInt(&key->n, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 467 | GetInt(&key->e, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 468 | GetInt(&key->d, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 469 | GetInt(&key->p, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 470 | GetInt(&key->q, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 471 | GetInt(&key->dP, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 472 | GetInt(&key->dQ, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 473 | GetInt(&key->u, input, inOutIdx) < 0 ) return ASN_RSA_KEY_E; |
toddouska | 0:5045d2638c29 | 474 | |
toddouska | 0:5045d2638c29 | 475 | return 0; |
toddouska | 0:5045d2638c29 | 476 | } |
toddouska | 0:5045d2638c29 | 477 | |
toddouska | 0:5045d2638c29 | 478 | |
toddouska | 0:5045d2638c29 | 479 | /* Remove PKCS8 header, move beginning of traditional to beginning of input */ |
toddouska | 0:5045d2638c29 | 480 | int ToTraditional(byte* input, word32 sz) |
toddouska | 0:5045d2638c29 | 481 | { |
toddouska | 0:5045d2638c29 | 482 | word32 inOutIdx = 0, oid; |
toddouska | 0:5045d2638c29 | 483 | int version, length; |
toddouska | 0:5045d2638c29 | 484 | |
toddouska | 0:5045d2638c29 | 485 | if (GetSequence(input, &inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 486 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 487 | |
toddouska | 0:5045d2638c29 | 488 | if ((word32)length > (sz - inOutIdx)) |
toddouska | 0:5045d2638c29 | 489 | return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 490 | |
toddouska | 0:5045d2638c29 | 491 | if (GetMyVersion(input, &inOutIdx, &version) < 0) |
toddouska | 0:5045d2638c29 | 492 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 493 | |
toddouska | 0:5045d2638c29 | 494 | if (GetAlgoId(input, &inOutIdx, &oid) < 0) |
toddouska | 0:5045d2638c29 | 495 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 496 | |
toddouska | 0:5045d2638c29 | 497 | if (input[inOutIdx++] != ASN_OCTET_STRING) |
toddouska | 0:5045d2638c29 | 498 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 499 | |
toddouska | 0:5045d2638c29 | 500 | if (GetLength(input, &inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 501 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 502 | |
toddouska | 0:5045d2638c29 | 503 | if ((word32)length > (sz - inOutIdx)) |
toddouska | 0:5045d2638c29 | 504 | return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 505 | |
toddouska | 0:5045d2638c29 | 506 | XMEMMOVE(input, input + inOutIdx, length); |
toddouska | 0:5045d2638c29 | 507 | |
toddouska | 0:5045d2638c29 | 508 | return 0; |
toddouska | 0:5045d2638c29 | 509 | } |
toddouska | 0:5045d2638c29 | 510 | |
toddouska | 0:5045d2638c29 | 511 | |
toddouska | 0:5045d2638c29 | 512 | int RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, |
toddouska | 0:5045d2638c29 | 513 | word32 inSz) |
toddouska | 0:5045d2638c29 | 514 | { |
toddouska | 0:5045d2638c29 | 515 | word32 begin = *inOutIdx; |
toddouska | 0:5045d2638c29 | 516 | int length; |
toddouska | 0:5045d2638c29 | 517 | byte b; |
toddouska | 0:5045d2638c29 | 518 | |
toddouska | 0:5045d2638c29 | 519 | if (GetSequence(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 520 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 521 | |
toddouska | 0:5045d2638c29 | 522 | if ((word32)length > (inSz - (*inOutIdx - begin))) |
toddouska | 0:5045d2638c29 | 523 | return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 524 | |
toddouska | 0:5045d2638c29 | 525 | key->type = RSA_PUBLIC; |
toddouska | 0:5045d2638c29 | 526 | b = input[*inOutIdx]; |
toddouska | 0:5045d2638c29 | 527 | |
toddouska | 0:5045d2638c29 | 528 | #ifdef OPENSSL_EXTRA |
toddouska | 0:5045d2638c29 | 529 | if (b != ASN_INTEGER) { |
toddouska | 0:5045d2638c29 | 530 | /* not from decoded cert, will have algo id, skip past */ |
toddouska | 0:5045d2638c29 | 531 | if (GetSequence(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 532 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 533 | |
toddouska | 0:5045d2638c29 | 534 | b = input[(*inOutIdx)++]; |
toddouska | 0:5045d2638c29 | 535 | if (b != ASN_OBJECT_ID) |
toddouska | 0:5045d2638c29 | 536 | return ASN_OBJECT_ID_E; |
toddouska | 0:5045d2638c29 | 537 | |
toddouska | 0:5045d2638c29 | 538 | if (GetLength(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 539 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 540 | |
toddouska | 0:5045d2638c29 | 541 | *inOutIdx += length; /* skip past */ |
toddouska | 0:5045d2638c29 | 542 | |
toddouska | 0:5045d2638c29 | 543 | /* could have NULL tag and 0 terminator, but may not */ |
toddouska | 0:5045d2638c29 | 544 | b = input[(*inOutIdx)++]; |
toddouska | 0:5045d2638c29 | 545 | |
toddouska | 0:5045d2638c29 | 546 | if (b == ASN_TAG_NULL) { |
toddouska | 0:5045d2638c29 | 547 | b = input[(*inOutIdx)++]; |
toddouska | 0:5045d2638c29 | 548 | if (b != 0) |
toddouska | 0:5045d2638c29 | 549 | return ASN_EXPECT_0_E; |
toddouska | 0:5045d2638c29 | 550 | } |
toddouska | 0:5045d2638c29 | 551 | else |
toddouska | 0:5045d2638c29 | 552 | /* go back, didn't have it */ |
toddouska | 0:5045d2638c29 | 553 | (*inOutIdx)--; |
toddouska | 0:5045d2638c29 | 554 | |
toddouska | 0:5045d2638c29 | 555 | /* should have bit tag length and seq next */ |
toddouska | 0:5045d2638c29 | 556 | b = input[(*inOutIdx)++]; |
toddouska | 0:5045d2638c29 | 557 | if (b != ASN_BIT_STRING) |
toddouska | 0:5045d2638c29 | 558 | return ASN_BITSTR_E; |
toddouska | 0:5045d2638c29 | 559 | |
toddouska | 0:5045d2638c29 | 560 | if (GetLength(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 561 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 562 | |
toddouska | 0:5045d2638c29 | 563 | /* could have 0 */ |
toddouska | 0:5045d2638c29 | 564 | b = input[(*inOutIdx)++]; |
toddouska | 0:5045d2638c29 | 565 | if (b != 0) |
toddouska | 0:5045d2638c29 | 566 | (*inOutIdx)--; |
toddouska | 0:5045d2638c29 | 567 | |
toddouska | 0:5045d2638c29 | 568 | if (GetSequence(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 569 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 570 | } |
toddouska | 0:5045d2638c29 | 571 | #endif /* OPENSSL_EXTRA */ |
toddouska | 0:5045d2638c29 | 572 | |
toddouska | 0:5045d2638c29 | 573 | if (GetInt(&key->n, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 574 | GetInt(&key->e, input, inOutIdx) < 0 ) return ASN_RSA_KEY_E; |
toddouska | 0:5045d2638c29 | 575 | |
toddouska | 0:5045d2638c29 | 576 | return 0; |
toddouska | 0:5045d2638c29 | 577 | } |
toddouska | 0:5045d2638c29 | 578 | |
toddouska | 0:5045d2638c29 | 579 | |
toddouska | 0:5045d2638c29 | 580 | #ifndef NO_DH |
toddouska | 0:5045d2638c29 | 581 | |
toddouska | 0:5045d2638c29 | 582 | int DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) |
toddouska | 0:5045d2638c29 | 583 | { |
toddouska | 0:5045d2638c29 | 584 | word32 begin = *inOutIdx; |
toddouska | 0:5045d2638c29 | 585 | int length; |
toddouska | 0:5045d2638c29 | 586 | |
toddouska | 0:5045d2638c29 | 587 | if (GetSequence(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 588 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 589 | |
toddouska | 0:5045d2638c29 | 590 | if ((word32)length > (inSz - (*inOutIdx - begin))) |
toddouska | 0:5045d2638c29 | 591 | return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 592 | |
toddouska | 0:5045d2638c29 | 593 | if (GetInt(&key->p, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 594 | GetInt(&key->g, input, inOutIdx) < 0 ) return ASN_DH_KEY_E; |
toddouska | 0:5045d2638c29 | 595 | |
toddouska | 0:5045d2638c29 | 596 | return 0; |
toddouska | 0:5045d2638c29 | 597 | } |
toddouska | 0:5045d2638c29 | 598 | |
toddouska | 0:5045d2638c29 | 599 | int DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz) |
toddouska | 0:5045d2638c29 | 600 | { |
toddouska | 0:5045d2638c29 | 601 | /* may have leading 0 */ |
toddouska | 0:5045d2638c29 | 602 | if (p[0] == 0) { |
toddouska | 0:5045d2638c29 | 603 | pSz--; p++; |
toddouska | 0:5045d2638c29 | 604 | } |
toddouska | 0:5045d2638c29 | 605 | |
toddouska | 0:5045d2638c29 | 606 | if (g[0] == 0) { |
toddouska | 0:5045d2638c29 | 607 | gSz--; g++; |
toddouska | 0:5045d2638c29 | 608 | } |
toddouska | 0:5045d2638c29 | 609 | |
toddouska | 0:5045d2638c29 | 610 | mp_init(&key->p); |
toddouska | 0:5045d2638c29 | 611 | if (mp_read_unsigned_bin(&key->p, p, pSz) != 0) { |
toddouska | 0:5045d2638c29 | 612 | mp_clear(&key->p); |
toddouska | 0:5045d2638c29 | 613 | return ASN_DH_KEY_E; |
toddouska | 0:5045d2638c29 | 614 | } |
toddouska | 0:5045d2638c29 | 615 | |
toddouska | 0:5045d2638c29 | 616 | mp_init(&key->g); |
toddouska | 0:5045d2638c29 | 617 | if (mp_read_unsigned_bin(&key->g, g, gSz) != 0) { |
toddouska | 0:5045d2638c29 | 618 | mp_clear(&key->p); |
toddouska | 0:5045d2638c29 | 619 | return ASN_DH_KEY_E; |
toddouska | 0:5045d2638c29 | 620 | } |
toddouska | 0:5045d2638c29 | 621 | |
toddouska | 0:5045d2638c29 | 622 | return 0; |
toddouska | 0:5045d2638c29 | 623 | } |
toddouska | 0:5045d2638c29 | 624 | |
toddouska | 0:5045d2638c29 | 625 | |
toddouska | 0:5045d2638c29 | 626 | #endif /* NO_DH */ |
toddouska | 0:5045d2638c29 | 627 | |
toddouska | 0:5045d2638c29 | 628 | |
toddouska | 0:5045d2638c29 | 629 | #ifndef NO_DSA |
toddouska | 0:5045d2638c29 | 630 | |
toddouska | 0:5045d2638c29 | 631 | int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, |
toddouska | 0:5045d2638c29 | 632 | word32 inSz) |
toddouska | 0:5045d2638c29 | 633 | { |
toddouska | 0:5045d2638c29 | 634 | word32 begin = *inOutIdx; |
toddouska | 0:5045d2638c29 | 635 | int length; |
toddouska | 0:5045d2638c29 | 636 | |
toddouska | 0:5045d2638c29 | 637 | if (GetSequence(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 638 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 639 | |
toddouska | 0:5045d2638c29 | 640 | if ((word32)length > (inSz - (*inOutIdx - begin))) |
toddouska | 0:5045d2638c29 | 641 | return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 642 | |
toddouska | 0:5045d2638c29 | 643 | if (GetInt(&key->p, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 644 | GetInt(&key->q, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 645 | GetInt(&key->g, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 646 | GetInt(&key->y, input, inOutIdx) < 0 ) return ASN_DH_KEY_E; |
toddouska | 0:5045d2638c29 | 647 | |
toddouska | 0:5045d2638c29 | 648 | key->type = DSA_PUBLIC; |
toddouska | 0:5045d2638c29 | 649 | return 0; |
toddouska | 0:5045d2638c29 | 650 | } |
toddouska | 0:5045d2638c29 | 651 | |
toddouska | 0:5045d2638c29 | 652 | |
toddouska | 0:5045d2638c29 | 653 | int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, |
toddouska | 0:5045d2638c29 | 654 | word32 inSz) |
toddouska | 0:5045d2638c29 | 655 | { |
toddouska | 0:5045d2638c29 | 656 | word32 begin = *inOutIdx; |
toddouska | 0:5045d2638c29 | 657 | int length, version; |
toddouska | 0:5045d2638c29 | 658 | |
toddouska | 0:5045d2638c29 | 659 | if (GetSequence(input, inOutIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 660 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 661 | |
toddouska | 0:5045d2638c29 | 662 | if ((word32)length > (inSz - (*inOutIdx - begin))) |
toddouska | 0:5045d2638c29 | 663 | return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 664 | |
toddouska | 0:5045d2638c29 | 665 | if (GetMyVersion(input, inOutIdx, &version) < 0) |
toddouska | 0:5045d2638c29 | 666 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 667 | |
toddouska | 0:5045d2638c29 | 668 | if (GetInt(&key->p, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 669 | GetInt(&key->q, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 670 | GetInt(&key->g, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 671 | GetInt(&key->y, input, inOutIdx) < 0 || |
toddouska | 0:5045d2638c29 | 672 | GetInt(&key->x, input, inOutIdx) < 0 ) return ASN_DH_KEY_E; |
toddouska | 0:5045d2638c29 | 673 | |
toddouska | 0:5045d2638c29 | 674 | key->type = DSA_PRIVATE; |
toddouska | 0:5045d2638c29 | 675 | return 0; |
toddouska | 0:5045d2638c29 | 676 | } |
toddouska | 0:5045d2638c29 | 677 | |
toddouska | 0:5045d2638c29 | 678 | #endif /* NO_DSA */ |
toddouska | 0:5045d2638c29 | 679 | |
toddouska | 0:5045d2638c29 | 680 | |
toddouska | 0:5045d2638c29 | 681 | void InitDecodedCert(DecodedCert* cert, byte* source, void* heap) |
toddouska | 0:5045d2638c29 | 682 | { |
toddouska | 0:5045d2638c29 | 683 | cert->publicKey = 0; |
toddouska | 0:5045d2638c29 | 684 | cert->pubKeyStored = 0; |
toddouska | 0:5045d2638c29 | 685 | cert->signature = 0; |
toddouska | 0:5045d2638c29 | 686 | cert->subjectCN = 0; |
toddouska | 0:5045d2638c29 | 687 | cert->subjectCNLen = 0; |
toddouska | 0:5045d2638c29 | 688 | cert->source = source; /* don't own */ |
toddouska | 0:5045d2638c29 | 689 | cert->srcIdx = 0; |
toddouska | 0:5045d2638c29 | 690 | cert->heap = heap; |
toddouska | 0:5045d2638c29 | 691 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 692 | cert->subjectSN = 0; |
toddouska | 0:5045d2638c29 | 693 | cert->subjectSNLen = 0; |
toddouska | 0:5045d2638c29 | 694 | cert->subjectC = 0; |
toddouska | 0:5045d2638c29 | 695 | cert->subjectCLen = 0; |
toddouska | 0:5045d2638c29 | 696 | cert->subjectL = 0; |
toddouska | 0:5045d2638c29 | 697 | cert->subjectLLen = 0; |
toddouska | 0:5045d2638c29 | 698 | cert->subjectST = 0; |
toddouska | 0:5045d2638c29 | 699 | cert->subjectSTLen = 0; |
toddouska | 0:5045d2638c29 | 700 | cert->subjectO = 0; |
toddouska | 0:5045d2638c29 | 701 | cert->subjectOLen = 0; |
toddouska | 0:5045d2638c29 | 702 | cert->subjectOU = 0; |
toddouska | 0:5045d2638c29 | 703 | cert->subjectOULen = 0; |
toddouska | 0:5045d2638c29 | 704 | cert->subjectEmail = 0; |
toddouska | 0:5045d2638c29 | 705 | cert->subjectEmailLen = 0; |
toddouska | 0:5045d2638c29 | 706 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 707 | } |
toddouska | 0:5045d2638c29 | 708 | |
toddouska | 0:5045d2638c29 | 709 | |
toddouska | 0:5045d2638c29 | 710 | void FreeDecodedCert(DecodedCert* cert) |
toddouska | 0:5045d2638c29 | 711 | { |
toddouska | 0:5045d2638c29 | 712 | if (cert->subjectCNLen == 0) /* 0 means no longer pointer to raw, we own */ |
toddouska | 0:5045d2638c29 | 713 | XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN); |
toddouska | 0:5045d2638c29 | 714 | if (cert->pubKeyStored == 1) |
toddouska | 0:5045d2638c29 | 715 | XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
toddouska | 0:5045d2638c29 | 716 | } |
toddouska | 0:5045d2638c29 | 717 | |
toddouska | 0:5045d2638c29 | 718 | |
toddouska | 0:5045d2638c29 | 719 | static int GetCertHeader(DecodedCert* cert, word32 inSz) |
toddouska | 0:5045d2638c29 | 720 | { |
toddouska | 0:5045d2638c29 | 721 | int ret = 0, version, len; |
toddouska | 0:5045d2638c29 | 722 | word32 begin = cert->srcIdx; |
toddouska | 0:5045d2638c29 | 723 | mp_int mpi; |
toddouska | 0:5045d2638c29 | 724 | |
toddouska | 0:5045d2638c29 | 725 | if (GetSequence(cert->source, &cert->srcIdx, &len) < 0) |
toddouska | 0:5045d2638c29 | 726 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 727 | |
toddouska | 0:5045d2638c29 | 728 | if ((word32)len > (inSz - (cert->srcIdx - begin))) return ASN_INPUT_E; |
toddouska | 0:5045d2638c29 | 729 | |
toddouska | 0:5045d2638c29 | 730 | cert->certBegin = cert->srcIdx; |
toddouska | 0:5045d2638c29 | 731 | |
toddouska | 0:5045d2638c29 | 732 | GetSequence(cert->source, &cert->srcIdx, &len); |
toddouska | 0:5045d2638c29 | 733 | cert->sigIndex = len + cert->srcIdx; |
toddouska | 0:5045d2638c29 | 734 | |
toddouska | 0:5045d2638c29 | 735 | if (GetExplicitVersion(cert->source, &cert->srcIdx, &version) < 0) |
toddouska | 0:5045d2638c29 | 736 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 737 | |
toddouska | 0:5045d2638c29 | 738 | if (GetInt(&mpi, cert->source, &cert->srcIdx) < 0) |
toddouska | 0:5045d2638c29 | 739 | ret = ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 740 | |
toddouska | 0:5045d2638c29 | 741 | mp_clear(&mpi); |
toddouska | 0:5045d2638c29 | 742 | return ret; |
toddouska | 0:5045d2638c29 | 743 | } |
toddouska | 0:5045d2638c29 | 744 | |
toddouska | 0:5045d2638c29 | 745 | |
toddouska | 0:5045d2638c29 | 746 | static int StoreKey(DecodedCert* cert) |
toddouska | 0:5045d2638c29 | 747 | { |
toddouska | 0:5045d2638c29 | 748 | int length; |
toddouska | 0:5045d2638c29 | 749 | word32 read = cert->srcIdx; |
toddouska | 0:5045d2638c29 | 750 | |
toddouska | 0:5045d2638c29 | 751 | if (cert->keyOID == NTRUk) |
toddouska | 0:5045d2638c29 | 752 | return 0; /* already stored */ |
toddouska | 0:5045d2638c29 | 753 | |
toddouska | 0:5045d2638c29 | 754 | if (GetSequence(cert->source, &cert->srcIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 755 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 756 | |
toddouska | 0:5045d2638c29 | 757 | read = cert->srcIdx - read; |
toddouska | 0:5045d2638c29 | 758 | length += read; |
toddouska | 0:5045d2638c29 | 759 | |
toddouska | 0:5045d2638c29 | 760 | while (read--) |
toddouska | 0:5045d2638c29 | 761 | cert->srcIdx--; |
toddouska | 0:5045d2638c29 | 762 | |
toddouska | 0:5045d2638c29 | 763 | cert->pubKeySize = length; |
toddouska | 0:5045d2638c29 | 764 | cert->publicKey = cert->source + cert->srcIdx; |
toddouska | 0:5045d2638c29 | 765 | cert->srcIdx += length; |
toddouska | 0:5045d2638c29 | 766 | |
toddouska | 0:5045d2638c29 | 767 | return 0; |
toddouska | 0:5045d2638c29 | 768 | } |
toddouska | 0:5045d2638c29 | 769 | |
toddouska | 0:5045d2638c29 | 770 | |
toddouska | 0:5045d2638c29 | 771 | static int GetKey(DecodedCert* cert) |
toddouska | 0:5045d2638c29 | 772 | { |
toddouska | 0:5045d2638c29 | 773 | int length; |
toddouska | 0:5045d2638c29 | 774 | #ifdef HAVE_NTRU |
toddouska | 0:5045d2638c29 | 775 | int tmpIdx = cert->srcIdx; |
toddouska | 0:5045d2638c29 | 776 | #endif |
toddouska | 0:5045d2638c29 | 777 | |
toddouska | 0:5045d2638c29 | 778 | if (GetSequence(cert->source, &cert->srcIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 779 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 780 | |
toddouska | 0:5045d2638c29 | 781 | if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID) < 0) |
toddouska | 0:5045d2638c29 | 782 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 783 | |
toddouska | 0:5045d2638c29 | 784 | if (cert->keyOID == RSAk) { |
toddouska | 0:5045d2638c29 | 785 | byte b = cert->source[cert->srcIdx++]; |
toddouska | 0:5045d2638c29 | 786 | if (b != ASN_BIT_STRING) |
toddouska | 0:5045d2638c29 | 787 | return ASN_BITSTR_E; |
toddouska | 0:5045d2638c29 | 788 | |
toddouska | 0:5045d2638c29 | 789 | if (GetLength(cert->source, &cert->srcIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 790 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 791 | b = cert->source[cert->srcIdx++]; |
toddouska | 0:5045d2638c29 | 792 | if (b != 0x00) |
toddouska | 0:5045d2638c29 | 793 | return ASN_EXPECT_0_E; |
toddouska | 0:5045d2638c29 | 794 | } |
toddouska | 0:5045d2638c29 | 795 | else if (cert->keyOID == DSAk ) |
toddouska | 0:5045d2638c29 | 796 | ; /* do nothing */ |
toddouska | 0:5045d2638c29 | 797 | #ifdef HAVE_NTRU |
toddouska | 0:5045d2638c29 | 798 | else if (cert->keyOID == NTRUk ) { |
toddouska | 0:5045d2638c29 | 799 | const byte* key = &cert->source[tmpIdx]; |
toddouska | 0:5045d2638c29 | 800 | byte* next = (byte*)key; |
toddouska | 0:5045d2638c29 | 801 | word16 keyLen; |
toddouska | 0:5045d2638c29 | 802 | byte keyBlob[MAX_NTRU_KEY_SZ]; |
toddouska | 0:5045d2638c29 | 803 | |
toddouska | 0:5045d2638c29 | 804 | word32 rc = crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key, |
toddouska | 0:5045d2638c29 | 805 | &keyLen, NULL, &next); |
toddouska | 0:5045d2638c29 | 806 | |
toddouska | 0:5045d2638c29 | 807 | if (rc != NTRU_OK) |
toddouska | 0:5045d2638c29 | 808 | return ASN_NTRU_KEY_E; |
toddouska | 0:5045d2638c29 | 809 | if (keyLen > sizeof(keyBlob)) |
toddouska | 0:5045d2638c29 | 810 | return ASN_NTRU_KEY_E; |
toddouska | 0:5045d2638c29 | 811 | |
toddouska | 0:5045d2638c29 | 812 | rc = crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key, &keyLen, |
toddouska | 0:5045d2638c29 | 813 | keyBlob, &next); |
toddouska | 0:5045d2638c29 | 814 | if (rc != NTRU_OK) |
toddouska | 0:5045d2638c29 | 815 | return ASN_NTRU_KEY_E; |
toddouska | 0:5045d2638c29 | 816 | |
toddouska | 0:5045d2638c29 | 817 | if ( (next - key) < 0) |
toddouska | 0:5045d2638c29 | 818 | return ASN_NTRU_KEY_E; |
toddouska | 0:5045d2638c29 | 819 | |
toddouska | 0:5045d2638c29 | 820 | cert->srcIdx = tmpIdx + (next - key); |
toddouska | 0:5045d2638c29 | 821 | |
toddouska | 0:5045d2638c29 | 822 | cert->publicKey = (byte*) XMALLOC(keyLen, cert->heap, |
toddouska | 0:5045d2638c29 | 823 | DYNAMIC_TYPE_PUBLIC_KEY); |
toddouska | 0:5045d2638c29 | 824 | if (cert->publicKey == NULL) |
toddouska | 0:5045d2638c29 | 825 | return MEMORY_E; |
toddouska | 0:5045d2638c29 | 826 | memcpy(cert->publicKey, keyBlob, keyLen); |
toddouska | 0:5045d2638c29 | 827 | cert->pubKeyStored = 1; |
toddouska | 0:5045d2638c29 | 828 | cert->pubKeySize = keyLen; |
toddouska | 0:5045d2638c29 | 829 | } |
toddouska | 0:5045d2638c29 | 830 | #endif |
toddouska | 0:5045d2638c29 | 831 | else |
toddouska | 0:5045d2638c29 | 832 | return ASN_UNKNOWN_OID_E; |
toddouska | 0:5045d2638c29 | 833 | |
toddouska | 0:5045d2638c29 | 834 | return StoreKey(cert); |
toddouska | 0:5045d2638c29 | 835 | } |
toddouska | 0:5045d2638c29 | 836 | |
toddouska | 0:5045d2638c29 | 837 | |
toddouska | 0:5045d2638c29 | 838 | /* process NAME, either issuer or subject */ |
toddouska | 0:5045d2638c29 | 839 | static int GetName(DecodedCert* cert, int nameType) |
toddouska | 0:5045d2638c29 | 840 | { |
toddouska | 0:5045d2638c29 | 841 | Sha sha; |
toddouska | 0:5045d2638c29 | 842 | int length; /* length of all distinguished names */ |
toddouska | 0:5045d2638c29 | 843 | int dummy; |
toddouska | 0:5045d2638c29 | 844 | char* full = (nameType == ISSUER) ? cert->issuer : cert->subject; |
toddouska | 0:5045d2638c29 | 845 | word32 idx = 0; |
toddouska | 0:5045d2638c29 | 846 | |
toddouska | 0:5045d2638c29 | 847 | InitSha(&sha); |
toddouska | 0:5045d2638c29 | 848 | |
toddouska | 0:5045d2638c29 | 849 | if (GetSequence(cert->source, &cert->srcIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 850 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 851 | |
toddouska | 0:5045d2638c29 | 852 | length += cert->srcIdx; |
toddouska | 0:5045d2638c29 | 853 | |
toddouska | 0:5045d2638c29 | 854 | while (cert->srcIdx < (word32)length) { |
toddouska | 0:5045d2638c29 | 855 | byte b; |
toddouska | 0:5045d2638c29 | 856 | byte joint[2]; |
toddouska | 0:5045d2638c29 | 857 | int oidSz; |
toddouska | 0:5045d2638c29 | 858 | |
toddouska | 0:5045d2638c29 | 859 | if (GetSet(cert->source, &cert->srcIdx, &dummy) < 0) |
toddouska | 0:5045d2638c29 | 860 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 861 | |
toddouska | 0:5045d2638c29 | 862 | if (GetSequence(cert->source, &cert->srcIdx, &dummy) < 0) |
toddouska | 0:5045d2638c29 | 863 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 864 | |
toddouska | 0:5045d2638c29 | 865 | b = cert->source[cert->srcIdx++]; |
toddouska | 0:5045d2638c29 | 866 | if (b != ASN_OBJECT_ID) |
toddouska | 0:5045d2638c29 | 867 | return ASN_OBJECT_ID_E; |
toddouska | 0:5045d2638c29 | 868 | |
toddouska | 0:5045d2638c29 | 869 | if (GetLength(cert->source, &cert->srcIdx, &oidSz) < 0) |
toddouska | 0:5045d2638c29 | 870 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 871 | |
toddouska | 0:5045d2638c29 | 872 | XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint)); |
toddouska | 0:5045d2638c29 | 873 | |
toddouska | 0:5045d2638c29 | 874 | /* v1 name types */ |
toddouska | 0:5045d2638c29 | 875 | if (joint[0] == 0x55 && joint[1] == 0x04) { |
toddouska | 0:5045d2638c29 | 876 | byte id; |
toddouska | 0:5045d2638c29 | 877 | byte copy = FALSE; |
toddouska | 0:5045d2638c29 | 878 | int strLen; |
toddouska | 0:5045d2638c29 | 879 | |
toddouska | 0:5045d2638c29 | 880 | cert->srcIdx += 2; |
toddouska | 0:5045d2638c29 | 881 | id = cert->source[cert->srcIdx++]; |
toddouska | 0:5045d2638c29 | 882 | b = cert->source[cert->srcIdx++]; /* strType */ |
toddouska | 0:5045d2638c29 | 883 | |
toddouska | 0:5045d2638c29 | 884 | if (GetLength(cert->source, &cert->srcIdx, &strLen) < 0) |
toddouska | 0:5045d2638c29 | 885 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 886 | |
toddouska | 0:5045d2638c29 | 887 | if (strLen > (int)(ASN_NAME_MAX - idx)) |
toddouska | 0:5045d2638c29 | 888 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 889 | |
toddouska | 0:5045d2638c29 | 890 | if (4 > (ASN_NAME_MAX - idx)) /* make sure room for biggest */ |
toddouska | 0:5045d2638c29 | 891 | return ASN_PARSE_E; /* pre fix header too "/CN=" */ |
toddouska | 0:5045d2638c29 | 892 | |
toddouska | 0:5045d2638c29 | 893 | if (id == ASN_COMMON_NAME) { |
toddouska | 0:5045d2638c29 | 894 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 895 | cert->subjectCN = (char *)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 896 | cert->subjectCNLen = strLen; |
toddouska | 0:5045d2638c29 | 897 | } |
toddouska | 0:5045d2638c29 | 898 | |
toddouska | 0:5045d2638c29 | 899 | XMEMCPY(&full[idx], "/CN=", 4); |
toddouska | 0:5045d2638c29 | 900 | idx += 4; |
toddouska | 0:5045d2638c29 | 901 | copy = TRUE; |
toddouska | 0:5045d2638c29 | 902 | } |
toddouska | 0:5045d2638c29 | 903 | else if (id == ASN_SUR_NAME) { |
toddouska | 0:5045d2638c29 | 904 | XMEMCPY(&full[idx], "/SN=", 4); |
toddouska | 0:5045d2638c29 | 905 | idx += 4; |
toddouska | 0:5045d2638c29 | 906 | copy = TRUE; |
toddouska | 0:5045d2638c29 | 907 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 908 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 909 | cert->subjectSN = (char*)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 910 | cert->subjectSNLen = strLen; |
toddouska | 0:5045d2638c29 | 911 | } |
toddouska | 0:5045d2638c29 | 912 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 913 | } |
toddouska | 0:5045d2638c29 | 914 | else if (id == ASN_COUNTRY_NAME) { |
toddouska | 0:5045d2638c29 | 915 | XMEMCPY(&full[idx], "/C=", 3); |
toddouska | 0:5045d2638c29 | 916 | idx += 3; |
toddouska | 0:5045d2638c29 | 917 | copy = TRUE; |
toddouska | 0:5045d2638c29 | 918 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 919 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 920 | cert->subjectC = (char*)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 921 | cert->subjectCLen = strLen; |
toddouska | 0:5045d2638c29 | 922 | } |
toddouska | 0:5045d2638c29 | 923 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 924 | } |
toddouska | 0:5045d2638c29 | 925 | else if (id == ASN_LOCALITY_NAME) { |
toddouska | 0:5045d2638c29 | 926 | XMEMCPY(&full[idx], "/L=", 3); |
toddouska | 0:5045d2638c29 | 927 | idx += 3; |
toddouska | 0:5045d2638c29 | 928 | copy = TRUE; |
toddouska | 0:5045d2638c29 | 929 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 930 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 931 | cert->subjectL = (char*)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 932 | cert->subjectLLen = strLen; |
toddouska | 0:5045d2638c29 | 933 | } |
toddouska | 0:5045d2638c29 | 934 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 935 | } |
toddouska | 0:5045d2638c29 | 936 | else if (id == ASN_STATE_NAME) { |
toddouska | 0:5045d2638c29 | 937 | XMEMCPY(&full[idx], "/ST=", 4); |
toddouska | 0:5045d2638c29 | 938 | idx += 4; |
toddouska | 0:5045d2638c29 | 939 | copy = TRUE; |
toddouska | 0:5045d2638c29 | 940 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 941 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 942 | cert->subjectST = (char*)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 943 | cert->subjectSTLen = strLen; |
toddouska | 0:5045d2638c29 | 944 | } |
toddouska | 0:5045d2638c29 | 945 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 946 | } |
toddouska | 0:5045d2638c29 | 947 | else if (id == ASN_ORG_NAME) { |
toddouska | 0:5045d2638c29 | 948 | XMEMCPY(&full[idx], "/O=", 3); |
toddouska | 0:5045d2638c29 | 949 | idx += 3; |
toddouska | 0:5045d2638c29 | 950 | copy = TRUE; |
toddouska | 0:5045d2638c29 | 951 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 952 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 953 | cert->subjectO = (char*)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 954 | cert->subjectOLen = strLen; |
toddouska | 0:5045d2638c29 | 955 | } |
toddouska | 0:5045d2638c29 | 956 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 957 | } |
toddouska | 0:5045d2638c29 | 958 | else if (id == ASN_ORGUNIT_NAME) { |
toddouska | 0:5045d2638c29 | 959 | XMEMCPY(&full[idx], "/OU=", 4); |
toddouska | 0:5045d2638c29 | 960 | idx += 4; |
toddouska | 0:5045d2638c29 | 961 | copy = TRUE; |
toddouska | 0:5045d2638c29 | 962 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 963 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 964 | cert->subjectOU = (char*)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 965 | cert->subjectOULen = strLen; |
toddouska | 0:5045d2638c29 | 966 | } |
toddouska | 0:5045d2638c29 | 967 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 968 | } |
toddouska | 0:5045d2638c29 | 969 | |
toddouska | 0:5045d2638c29 | 970 | if (copy) { |
toddouska | 0:5045d2638c29 | 971 | XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen); |
toddouska | 0:5045d2638c29 | 972 | idx += strLen; |
toddouska | 0:5045d2638c29 | 973 | } |
toddouska | 0:5045d2638c29 | 974 | |
toddouska | 0:5045d2638c29 | 975 | ShaUpdate(&sha, &cert->source[cert->srcIdx], strLen); |
toddouska | 0:5045d2638c29 | 976 | cert->srcIdx += strLen; |
toddouska | 0:5045d2638c29 | 977 | } |
toddouska | 0:5045d2638c29 | 978 | else { |
toddouska | 0:5045d2638c29 | 979 | /* skip */ |
toddouska | 0:5045d2638c29 | 980 | byte email = FALSE; |
toddouska | 0:5045d2638c29 | 981 | int adv; |
toddouska | 0:5045d2638c29 | 982 | |
toddouska | 0:5045d2638c29 | 983 | if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */ |
toddouska | 0:5045d2638c29 | 984 | email = TRUE; |
toddouska | 0:5045d2638c29 | 985 | |
toddouska | 0:5045d2638c29 | 986 | cert->srcIdx += oidSz + 1; |
toddouska | 0:5045d2638c29 | 987 | |
toddouska | 0:5045d2638c29 | 988 | if (GetLength(cert->source, &cert->srcIdx, &adv) < 0) |
toddouska | 0:5045d2638c29 | 989 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 990 | |
toddouska | 0:5045d2638c29 | 991 | if (adv > (int)(ASN_NAME_MAX - idx)) |
toddouska | 0:5045d2638c29 | 992 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 993 | |
toddouska | 0:5045d2638c29 | 994 | if (email) { |
toddouska | 0:5045d2638c29 | 995 | if (14 > (ASN_NAME_MAX - idx)) |
toddouska | 0:5045d2638c29 | 996 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 997 | XMEMCPY(&full[idx], "/emailAddress=", 14); |
toddouska | 0:5045d2638c29 | 998 | idx += 14; |
toddouska | 0:5045d2638c29 | 999 | |
toddouska | 0:5045d2638c29 | 1000 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 1001 | if (nameType == SUBJECT) { |
toddouska | 0:5045d2638c29 | 1002 | cert->subjectEmail = (char*)&cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 1003 | cert->subjectEmailLen = adv; |
toddouska | 0:5045d2638c29 | 1004 | } |
toddouska | 0:5045d2638c29 | 1005 | #endif /* CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 1006 | |
toddouska | 0:5045d2638c29 | 1007 | XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); |
toddouska | 0:5045d2638c29 | 1008 | idx += adv; |
toddouska | 0:5045d2638c29 | 1009 | } |
toddouska | 0:5045d2638c29 | 1010 | |
toddouska | 0:5045d2638c29 | 1011 | cert->srcIdx += adv; |
toddouska | 0:5045d2638c29 | 1012 | } |
toddouska | 0:5045d2638c29 | 1013 | } |
toddouska | 0:5045d2638c29 | 1014 | full[idx++] = 0; |
toddouska | 0:5045d2638c29 | 1015 | |
toddouska | 0:5045d2638c29 | 1016 | if (nameType == ISSUER) |
toddouska | 0:5045d2638c29 | 1017 | ShaFinal(&sha, cert->issuerHash); |
toddouska | 0:5045d2638c29 | 1018 | else |
toddouska | 0:5045d2638c29 | 1019 | ShaFinal(&sha, cert->subjectHash); |
toddouska | 0:5045d2638c29 | 1020 | |
toddouska | 0:5045d2638c29 | 1021 | return 0; |
toddouska | 0:5045d2638c29 | 1022 | } |
toddouska | 0:5045d2638c29 | 1023 | |
toddouska | 0:5045d2638c29 | 1024 | |
toddouska | 0:5045d2638c29 | 1025 | #ifndef NO_TIME_H |
toddouska | 0:5045d2638c29 | 1026 | |
toddouska | 0:5045d2638c29 | 1027 | /* to the second */ |
toddouska | 0:5045d2638c29 | 1028 | static int DateGreaterThan(const struct tm* a, const struct tm* b) |
toddouska | 0:5045d2638c29 | 1029 | { |
toddouska | 0:5045d2638c29 | 1030 | if (a->tm_year > b->tm_year) |
toddouska | 0:5045d2638c29 | 1031 | return 1; |
toddouska | 0:5045d2638c29 | 1032 | |
toddouska | 0:5045d2638c29 | 1033 | if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon) |
toddouska | 0:5045d2638c29 | 1034 | return 1; |
toddouska | 0:5045d2638c29 | 1035 | |
toddouska | 0:5045d2638c29 | 1036 | if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && |
toddouska | 0:5045d2638c29 | 1037 | a->tm_mday > b->tm_mday) |
toddouska | 0:5045d2638c29 | 1038 | return 1; |
toddouska | 0:5045d2638c29 | 1039 | |
toddouska | 0:5045d2638c29 | 1040 | if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && |
toddouska | 0:5045d2638c29 | 1041 | a->tm_mday == b->tm_mday && a->tm_hour > b->tm_hour) |
toddouska | 0:5045d2638c29 | 1042 | return 1; |
toddouska | 0:5045d2638c29 | 1043 | |
toddouska | 0:5045d2638c29 | 1044 | if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && |
toddouska | 0:5045d2638c29 | 1045 | a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour && |
toddouska | 0:5045d2638c29 | 1046 | a->tm_min > b->tm_min) |
toddouska | 0:5045d2638c29 | 1047 | return 1; |
toddouska | 0:5045d2638c29 | 1048 | |
toddouska | 0:5045d2638c29 | 1049 | if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && |
toddouska | 0:5045d2638c29 | 1050 | a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour && |
toddouska | 0:5045d2638c29 | 1051 | a->tm_min == b->tm_min && a->tm_sec > b->tm_sec) |
toddouska | 0:5045d2638c29 | 1052 | return 1; |
toddouska | 0:5045d2638c29 | 1053 | |
toddouska | 0:5045d2638c29 | 1054 | return 0; /* false */ |
toddouska | 0:5045d2638c29 | 1055 | } |
toddouska | 0:5045d2638c29 | 1056 | |
toddouska | 0:5045d2638c29 | 1057 | |
toddouska | 0:5045d2638c29 | 1058 | static INLINE int DateLessThan(const struct tm* a, const struct tm* b) |
toddouska | 0:5045d2638c29 | 1059 | { |
toddouska | 0:5045d2638c29 | 1060 | return !DateGreaterThan(a,b); |
toddouska | 0:5045d2638c29 | 1061 | } |
toddouska | 0:5045d2638c29 | 1062 | |
toddouska | 0:5045d2638c29 | 1063 | |
toddouska | 0:5045d2638c29 | 1064 | /* like atoi but only use first byte */ |
toddouska | 0:5045d2638c29 | 1065 | /* Make sure before and after dates are valid */ |
toddouska | 0:5045d2638c29 | 1066 | static int ValidateDate(const byte* date, byte format, int dateType) |
toddouska | 0:5045d2638c29 | 1067 | { |
toddouska | 0:5045d2638c29 | 1068 | time_t ltime; |
toddouska | 0:5045d2638c29 | 1069 | struct tm certTime; |
toddouska | 0:5045d2638c29 | 1070 | struct tm* localTime; |
toddouska | 0:5045d2638c29 | 1071 | int i = 0; |
toddouska | 0:5045d2638c29 | 1072 | |
toddouska | 0:5045d2638c29 | 1073 | ltime = XTIME(0); |
toddouska | 0:5045d2638c29 | 1074 | XMEMSET(&certTime, 0, sizeof(certTime)); |
toddouska | 0:5045d2638c29 | 1075 | |
toddouska | 0:5045d2638c29 | 1076 | if (format == ASN_UTC_TIME) { |
toddouska | 0:5045d2638c29 | 1077 | if (btoi(date[0]) >= 5) |
toddouska | 0:5045d2638c29 | 1078 | certTime.tm_year = 1900; |
toddouska | 0:5045d2638c29 | 1079 | else |
toddouska | 0:5045d2638c29 | 1080 | certTime.tm_year = 2000; |
toddouska | 0:5045d2638c29 | 1081 | } |
toddouska | 0:5045d2638c29 | 1082 | else { /* format == GENERALIZED_TIME */ |
toddouska | 0:5045d2638c29 | 1083 | certTime.tm_year += btoi(date[i++]) * 1000; |
toddouska | 0:5045d2638c29 | 1084 | certTime.tm_year += btoi(date[i++]) * 100; |
toddouska | 0:5045d2638c29 | 1085 | } |
toddouska | 0:5045d2638c29 | 1086 | |
toddouska | 0:5045d2638c29 | 1087 | GetTime(&certTime.tm_year, date, &i); certTime.tm_year -= 1900; /* adjust */ |
toddouska | 0:5045d2638c29 | 1088 | GetTime(&certTime.tm_mon, date, &i); certTime.tm_mon -= 1; /* adjust */ |
toddouska | 0:5045d2638c29 | 1089 | GetTime(&certTime.tm_mday, date, &i); |
toddouska | 0:5045d2638c29 | 1090 | GetTime(&certTime.tm_hour, date, &i); |
toddouska | 0:5045d2638c29 | 1091 | GetTime(&certTime.tm_min, date, &i); |
toddouska | 0:5045d2638c29 | 1092 | GetTime(&certTime.tm_sec, date, &i); |
toddouska | 0:5045d2638c29 | 1093 | |
toddouska | 0:5045d2638c29 | 1094 | if (date[i] != 'Z') /* only Zulu supported for this profile */ |
toddouska | 0:5045d2638c29 | 1095 | return 0; |
toddouska | 0:5045d2638c29 | 1096 | |
toddouska | 0:5045d2638c29 | 1097 | localTime = XGMTIME(<ime); |
toddouska | 0:5045d2638c29 | 1098 | |
toddouska | 0:5045d2638c29 | 1099 | if (dateType == BEFORE) { |
toddouska | 0:5045d2638c29 | 1100 | if (DateLessThan(localTime, &certTime)) |
toddouska | 0:5045d2638c29 | 1101 | return 0; |
toddouska | 0:5045d2638c29 | 1102 | } |
toddouska | 0:5045d2638c29 | 1103 | else |
toddouska | 0:5045d2638c29 | 1104 | if (DateGreaterThan(localTime, &certTime)) |
toddouska | 0:5045d2638c29 | 1105 | return 0; |
toddouska | 0:5045d2638c29 | 1106 | |
toddouska | 0:5045d2638c29 | 1107 | return 1; |
toddouska | 0:5045d2638c29 | 1108 | } |
toddouska | 0:5045d2638c29 | 1109 | |
toddouska | 0:5045d2638c29 | 1110 | #endif /* NO_TIME_H */ |
toddouska | 0:5045d2638c29 | 1111 | |
toddouska | 0:5045d2638c29 | 1112 | |
toddouska | 0:5045d2638c29 | 1113 | static int GetDate(DecodedCert* cert, int dateType) |
toddouska | 0:5045d2638c29 | 1114 | { |
toddouska | 0:5045d2638c29 | 1115 | int length; |
toddouska | 0:5045d2638c29 | 1116 | byte date[MAX_DATE_SIZE]; |
toddouska | 0:5045d2638c29 | 1117 | byte b = cert->source[cert->srcIdx++]; |
toddouska | 0:5045d2638c29 | 1118 | |
toddouska | 0:5045d2638c29 | 1119 | if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) |
toddouska | 0:5045d2638c29 | 1120 | return ASN_TIME_E; |
toddouska | 0:5045d2638c29 | 1121 | |
toddouska | 0:5045d2638c29 | 1122 | if (GetLength(cert->source, &cert->srcIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 1123 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 1124 | |
toddouska | 0:5045d2638c29 | 1125 | if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE) |
toddouska | 0:5045d2638c29 | 1126 | return ASN_DATE_SZ_E; |
toddouska | 0:5045d2638c29 | 1127 | |
toddouska | 0:5045d2638c29 | 1128 | XMEMCPY(date, &cert->source[cert->srcIdx], length); |
toddouska | 0:5045d2638c29 | 1129 | cert->srcIdx += length; |
toddouska | 0:5045d2638c29 | 1130 | |
toddouska | 0:5045d2638c29 | 1131 | if (!XVALIDATE_DATE(date, b, dateType)) { |
toddouska | 0:5045d2638c29 | 1132 | if (dateType == BEFORE) |
toddouska | 0:5045d2638c29 | 1133 | return ASN_BEFORE_DATE_E; |
toddouska | 0:5045d2638c29 | 1134 | else |
toddouska | 0:5045d2638c29 | 1135 | return ASN_AFTER_DATE_E; |
toddouska | 0:5045d2638c29 | 1136 | } |
toddouska | 0:5045d2638c29 | 1137 | |
toddouska | 0:5045d2638c29 | 1138 | return 0; |
toddouska | 0:5045d2638c29 | 1139 | } |
toddouska | 0:5045d2638c29 | 1140 | |
toddouska | 0:5045d2638c29 | 1141 | |
toddouska | 0:5045d2638c29 | 1142 | static int GetValidity(DecodedCert* cert, int verify) |
toddouska | 0:5045d2638c29 | 1143 | { |
toddouska | 0:5045d2638c29 | 1144 | int length; |
toddouska | 0:5045d2638c29 | 1145 | int badDate = 0; |
toddouska | 0:5045d2638c29 | 1146 | |
toddouska | 0:5045d2638c29 | 1147 | if (GetSequence(cert->source, &cert->srcIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 1148 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 1149 | |
toddouska | 0:5045d2638c29 | 1150 | if (GetDate(cert, BEFORE) < 0 && verify) |
toddouska | 0:5045d2638c29 | 1151 | badDate = ASN_BEFORE_DATE_E; /* continue parsing */ |
toddouska | 0:5045d2638c29 | 1152 | |
toddouska | 0:5045d2638c29 | 1153 | if (GetDate(cert, AFTER) < 0 && verify) |
toddouska | 0:5045d2638c29 | 1154 | return ASN_AFTER_DATE_E; |
toddouska | 0:5045d2638c29 | 1155 | |
toddouska | 0:5045d2638c29 | 1156 | if (badDate != 0) |
toddouska | 0:5045d2638c29 | 1157 | return badDate; |
toddouska | 0:5045d2638c29 | 1158 | |
toddouska | 0:5045d2638c29 | 1159 | return 0; |
toddouska | 0:5045d2638c29 | 1160 | } |
toddouska | 0:5045d2638c29 | 1161 | |
toddouska | 0:5045d2638c29 | 1162 | |
toddouska | 0:5045d2638c29 | 1163 | static int DecodeToKey(DecodedCert* cert, word32 inSz, int verify) |
toddouska | 0:5045d2638c29 | 1164 | { |
toddouska | 0:5045d2638c29 | 1165 | int badDate = 0; |
toddouska | 0:5045d2638c29 | 1166 | int ret; |
toddouska | 0:5045d2638c29 | 1167 | |
toddouska | 0:5045d2638c29 | 1168 | if ( (ret = GetCertHeader(cert, inSz)) < 0) |
toddouska | 0:5045d2638c29 | 1169 | return ret; |
toddouska | 0:5045d2638c29 | 1170 | |
toddouska | 0:5045d2638c29 | 1171 | if ( (ret = GetAlgoId(cert->source, &cert->srcIdx,&cert->signatureOID)) < 0) |
toddouska | 0:5045d2638c29 | 1172 | return ret; |
toddouska | 0:5045d2638c29 | 1173 | |
toddouska | 0:5045d2638c29 | 1174 | if ( (ret = GetName(cert, ISSUER)) < 0) |
toddouska | 0:5045d2638c29 | 1175 | return ret; |
toddouska | 0:5045d2638c29 | 1176 | |
toddouska | 0:5045d2638c29 | 1177 | if ( (ret = GetValidity(cert, verify)) < 0) |
toddouska | 0:5045d2638c29 | 1178 | badDate = ret; |
toddouska | 0:5045d2638c29 | 1179 | |
toddouska | 0:5045d2638c29 | 1180 | if ( (ret = GetName(cert, SUBJECT)) < 0) |
toddouska | 0:5045d2638c29 | 1181 | return ret; |
toddouska | 0:5045d2638c29 | 1182 | |
toddouska | 0:5045d2638c29 | 1183 | if ( (ret = GetKey(cert)) < 0) |
toddouska | 0:5045d2638c29 | 1184 | return ret; |
toddouska | 0:5045d2638c29 | 1185 | |
toddouska | 0:5045d2638c29 | 1186 | if (badDate != 0) |
toddouska | 0:5045d2638c29 | 1187 | return badDate; |
toddouska | 0:5045d2638c29 | 1188 | |
toddouska | 0:5045d2638c29 | 1189 | return ret; |
toddouska | 0:5045d2638c29 | 1190 | } |
toddouska | 0:5045d2638c29 | 1191 | |
toddouska | 0:5045d2638c29 | 1192 | |
toddouska | 0:5045d2638c29 | 1193 | static int GetSignature(DecodedCert* cert) |
toddouska | 0:5045d2638c29 | 1194 | { |
toddouska | 0:5045d2638c29 | 1195 | int length; |
toddouska | 0:5045d2638c29 | 1196 | byte b = cert->source[cert->srcIdx++]; |
toddouska | 0:5045d2638c29 | 1197 | |
toddouska | 0:5045d2638c29 | 1198 | if (b != ASN_BIT_STRING) |
toddouska | 0:5045d2638c29 | 1199 | return ASN_BITSTR_E; |
toddouska | 0:5045d2638c29 | 1200 | |
toddouska | 0:5045d2638c29 | 1201 | if (GetLength(cert->source, &cert->srcIdx, &length) < 0) |
toddouska | 0:5045d2638c29 | 1202 | return ASN_PARSE_E; |
toddouska | 0:5045d2638c29 | 1203 | |
toddouska | 0:5045d2638c29 | 1204 | cert->sigLength = length; |
toddouska | 0:5045d2638c29 | 1205 | |
toddouska | 0:5045d2638c29 | 1206 | b = cert->source[cert->srcIdx++]; |
toddouska | 0:5045d2638c29 | 1207 | if (b != 0x00) |
toddouska | 0:5045d2638c29 | 1208 | return ASN_EXPECT_0_E; |
toddouska | 0:5045d2638c29 | 1209 | |
toddouska | 0:5045d2638c29 | 1210 | cert->sigLength--; |
toddouska | 0:5045d2638c29 | 1211 | cert->signature = &cert->source[cert->srcIdx]; |
toddouska | 0:5045d2638c29 | 1212 | cert->srcIdx += cert->sigLength; |
toddouska | 0:5045d2638c29 | 1213 | |
toddouska | 0:5045d2638c29 | 1214 | return 0; |
toddouska | 0:5045d2638c29 | 1215 | } |
toddouska | 0:5045d2638c29 | 1216 | |
toddouska | 0:5045d2638c29 | 1217 | |
toddouska | 0:5045d2638c29 | 1218 | static word32 SetDigest(const byte* digest, word32 digSz, byte* output) |
toddouska | 0:5045d2638c29 | 1219 | { |
toddouska | 0:5045d2638c29 | 1220 | output[0] = ASN_OCTET_STRING; |
toddouska | 0:5045d2638c29 | 1221 | output[1] = digSz; |
toddouska | 0:5045d2638c29 | 1222 | XMEMCPY(&output[2], digest, digSz); |
toddouska | 0:5045d2638c29 | 1223 | |
toddouska | 0:5045d2638c29 | 1224 | return digSz + 2; |
toddouska | 0:5045d2638c29 | 1225 | } |
toddouska | 0:5045d2638c29 | 1226 | |
toddouska | 0:5045d2638c29 | 1227 | |
toddouska | 0:5045d2638c29 | 1228 | static word32 BytePrecision(word32 value) |
toddouska | 0:5045d2638c29 | 1229 | { |
toddouska | 0:5045d2638c29 | 1230 | word32 i; |
toddouska | 0:5045d2638c29 | 1231 | for (i = sizeof(value); i; --i) |
toddouska | 0:5045d2638c29 | 1232 | if (value >> (i - 1) * 8) |
toddouska | 0:5045d2638c29 | 1233 | break; |
toddouska | 0:5045d2638c29 | 1234 | |
toddouska | 0:5045d2638c29 | 1235 | return i; |
toddouska | 0:5045d2638c29 | 1236 | } |
toddouska | 0:5045d2638c29 | 1237 | |
toddouska | 0:5045d2638c29 | 1238 | |
toddouska | 0:5045d2638c29 | 1239 | static word32 SetLength(word32 length, byte* output) |
toddouska | 0:5045d2638c29 | 1240 | { |
toddouska | 0:5045d2638c29 | 1241 | word32 i = 0, j; |
toddouska | 0:5045d2638c29 | 1242 | |
toddouska | 0:5045d2638c29 | 1243 | if (length < ASN_LONG_LENGTH) |
toddouska | 0:5045d2638c29 | 1244 | output[i++] = length; |
toddouska | 0:5045d2638c29 | 1245 | else { |
toddouska | 0:5045d2638c29 | 1246 | output[i++] = BytePrecision(length) | ASN_LONG_LENGTH; |
toddouska | 0:5045d2638c29 | 1247 | |
toddouska | 0:5045d2638c29 | 1248 | for (j = BytePrecision(length); j; --j) { |
toddouska | 0:5045d2638c29 | 1249 | output[i] = length >> (j - 1) * 8; |
toddouska | 0:5045d2638c29 | 1250 | i++; |
toddouska | 0:5045d2638c29 | 1251 | } |
toddouska | 0:5045d2638c29 | 1252 | } |
toddouska | 0:5045d2638c29 | 1253 | |
toddouska | 0:5045d2638c29 | 1254 | return i; |
toddouska | 0:5045d2638c29 | 1255 | } |
toddouska | 0:5045d2638c29 | 1256 | |
toddouska | 0:5045d2638c29 | 1257 | |
toddouska | 0:5045d2638c29 | 1258 | static word32 SetSequence(word32 len, byte* output) |
toddouska | 0:5045d2638c29 | 1259 | { |
toddouska | 0:5045d2638c29 | 1260 | output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; |
toddouska | 0:5045d2638c29 | 1261 | return SetLength(len, output + 1) + 1; |
toddouska | 0:5045d2638c29 | 1262 | } |
toddouska | 0:5045d2638c29 | 1263 | |
toddouska | 0:5045d2638c29 | 1264 | |
toddouska | 0:5045d2638c29 | 1265 | static word32 SetAlgoID(int algoOID, byte* output, int type) |
toddouska | 0:5045d2638c29 | 1266 | { |
toddouska | 0:5045d2638c29 | 1267 | /* adding TAG_NULL and 0 to end */ |
toddouska | 0:5045d2638c29 | 1268 | |
toddouska | 0:5045d2638c29 | 1269 | /* hashTypes */ |
toddouska | 0:5045d2638c29 | 1270 | static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a, |
toddouska | 0:5045d2638c29 | 1271 | 0x05, 0x00 }; |
toddouska | 0:5045d2638c29 | 1272 | static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, |
toddouska | 0:5045d2638c29 | 1273 | 0x02, 0x05, 0x05, 0x00 }; |
toddouska | 0:5045d2638c29 | 1274 | static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, |
toddouska | 0:5045d2638c29 | 1275 | 0x02, 0x02, 0x05, 0x00}; |
toddouska | 0:5045d2638c29 | 1276 | |
toddouska | 0:5045d2638c29 | 1277 | /* sigTypes */ |
toddouska | 0:5045d2638c29 | 1278 | static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, |
toddouska | 0:5045d2638c29 | 1279 | 0x01, 0x01, 0x04, 0x05, 0x00}; |
toddouska | 0:5045d2638c29 | 1280 | |
toddouska | 0:5045d2638c29 | 1281 | /* keyTypes */ |
toddouska | 0:5045d2638c29 | 1282 | static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, |
toddouska | 0:5045d2638c29 | 1283 | 0x01, 0x01, 0x01, 0x05, 0x00}; |
toddouska | 0:5045d2638c29 | 1284 | |
toddouska | 0:5045d2638c29 | 1285 | int algoSz = 0; |
toddouska | 0:5045d2638c29 | 1286 | word32 idSz, seqSz; |
toddouska | 0:5045d2638c29 | 1287 | const byte* algoName = 0; |
toddouska | 0:5045d2638c29 | 1288 | byte ID_Length[MAX_LENGTH_SZ]; |
toddouska | 0:5045d2638c29 | 1289 | byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ |
toddouska | 0:5045d2638c29 | 1290 | |
toddouska | 0:5045d2638c29 | 1291 | if (type == hashType) { |
toddouska | 0:5045d2638c29 | 1292 | switch (algoOID) { |
toddouska | 0:5045d2638c29 | 1293 | case SHAh: |
toddouska | 0:5045d2638c29 | 1294 | algoSz = sizeof(shaAlgoID); |
toddouska | 0:5045d2638c29 | 1295 | algoName = shaAlgoID; |
toddouska | 0:5045d2638c29 | 1296 | break; |
toddouska | 0:5045d2638c29 | 1297 | |
toddouska | 0:5045d2638c29 | 1298 | case MD2h: |
toddouska | 0:5045d2638c29 | 1299 | algoSz = sizeof(md2AlgoID); |
toddouska | 0:5045d2638c29 | 1300 | algoName = md2AlgoID; |
toddouska | 0:5045d2638c29 | 1301 | break; |
toddouska | 0:5045d2638c29 | 1302 | |
toddouska | 0:5045d2638c29 | 1303 | case MD5h: |
toddouska | 0:5045d2638c29 | 1304 | algoSz = sizeof(md5AlgoID); |
toddouska | 0:5045d2638c29 | 1305 | algoName = md5AlgoID; |
toddouska | 0:5045d2638c29 | 1306 | break; |
toddouska | 0:5045d2638c29 | 1307 | |
toddouska | 0:5045d2638c29 | 1308 | default: |
toddouska | 0:5045d2638c29 | 1309 | return 0; /* UNKOWN_HASH_E; */ |
toddouska | 0:5045d2638c29 | 1310 | } |
toddouska | 0:5045d2638c29 | 1311 | } |
toddouska | 0:5045d2638c29 | 1312 | else if (type == sigType) { /* sigType */ |
toddouska | 0:5045d2638c29 | 1313 | switch (algoOID) { |
toddouska | 0:5045d2638c29 | 1314 | case MD5wRSA: |
toddouska | 0:5045d2638c29 | 1315 | algoSz = sizeof(md5wRSA_AlgoID); |
toddouska | 0:5045d2638c29 | 1316 | algoName = md5wRSA_AlgoID; |
toddouska | 0:5045d2638c29 | 1317 | break; |
toddouska | 0:5045d2638c29 | 1318 | |
toddouska | 0:5045d2638c29 | 1319 | default: |
toddouska | 0:5045d2638c29 | 1320 | return 0; /* UNKOWN_HASH_E; */ |
toddouska | 0:5045d2638c29 | 1321 | } |
toddouska | 0:5045d2638c29 | 1322 | } |
toddouska | 0:5045d2638c29 | 1323 | else if (type == keyType) { /* keyType */ |
toddouska | 0:5045d2638c29 | 1324 | switch (algoOID) { |
toddouska | 0:5045d2638c29 | 1325 | case RSAk: |
toddouska | 0:5045d2638c29 | 1326 | algoSz = sizeof(RSA_AlgoID); |
toddouska | 0:5045d2638c29 | 1327 | algoName = RSA_AlgoID; |
toddouska | 0:5045d2638c29 | 1328 | break; |
toddouska | 0:5045d2638c29 | 1329 | |
toddouska | 0:5045d2638c29 | 1330 | default: |
toddouska | 0:5045d2638c29 | 1331 | return 0; /* UNKOWN_HASH_E; */ |
toddouska | 0:5045d2638c29 | 1332 | } |
toddouska | 0:5045d2638c29 | 1333 | } |
toddouska | 0:5045d2638c29 | 1334 | else |
toddouska | 0:5045d2638c29 | 1335 | return 0; /* UNKNOWN_TYPE */ |
toddouska | 0:5045d2638c29 | 1336 | |
toddouska | 0:5045d2638c29 | 1337 | |
toddouska | 0:5045d2638c29 | 1338 | idSz = SetLength(algoSz - 2, ID_Length); /* don't include TAG_NULL/0 */ |
toddouska | 0:5045d2638c29 | 1339 | seqSz = SetSequence(idSz + algoSz + 1, seqArray); |
toddouska | 0:5045d2638c29 | 1340 | seqArray[seqSz++] = ASN_OBJECT_ID; |
toddouska | 0:5045d2638c29 | 1341 | |
toddouska | 0:5045d2638c29 | 1342 | XMEMCPY(output, seqArray, seqSz); |
toddouska | 0:5045d2638c29 | 1343 | XMEMCPY(output + seqSz, ID_Length, idSz); |
toddouska | 0:5045d2638c29 | 1344 | XMEMCPY(output + seqSz + idSz, algoName, algoSz); |
toddouska | 0:5045d2638c29 | 1345 | |
toddouska | 0:5045d2638c29 | 1346 | return seqSz + idSz + algoSz; |
toddouska | 0:5045d2638c29 | 1347 | |
toddouska | 0:5045d2638c29 | 1348 | } |
toddouska | 0:5045d2638c29 | 1349 | |
toddouska | 0:5045d2638c29 | 1350 | |
toddouska | 0:5045d2638c29 | 1351 | word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID) |
toddouska | 0:5045d2638c29 | 1352 | { |
toddouska | 0:5045d2638c29 | 1353 | byte digArray[MAX_ENCODED_DIG_SZ]; |
toddouska | 0:5045d2638c29 | 1354 | byte algoArray[MAX_ALGO_SZ]; |
toddouska | 0:5045d2638c29 | 1355 | byte seqArray[MAX_SEQ_SZ]; |
toddouska | 0:5045d2638c29 | 1356 | word32 encDigSz, algoSz, seqSz; |
toddouska | 0:5045d2638c29 | 1357 | |
toddouska | 0:5045d2638c29 | 1358 | encDigSz = SetDigest(digest, digSz, digArray); |
toddouska | 0:5045d2638c29 | 1359 | algoSz = SetAlgoID(hashOID, algoArray, hashType); |
toddouska | 0:5045d2638c29 | 1360 | seqSz = SetSequence(encDigSz + algoSz, seqArray); |
toddouska | 0:5045d2638c29 | 1361 | |
toddouska | 0:5045d2638c29 | 1362 | XMEMCPY(out, seqArray, seqSz); |
toddouska | 0:5045d2638c29 | 1363 | XMEMCPY(out + seqSz, algoArray, algoSz); |
toddouska | 0:5045d2638c29 | 1364 | XMEMCPY(out + seqSz + algoSz, digArray, encDigSz); |
toddouska | 0:5045d2638c29 | 1365 | |
toddouska | 0:5045d2638c29 | 1366 | return encDigSz + algoSz + seqSz; |
toddouska | 0:5045d2638c29 | 1367 | } |
toddouska | 0:5045d2638c29 | 1368 | |
toddouska | 0:5045d2638c29 | 1369 | |
toddouska | 0:5045d2638c29 | 1370 | /* return true (1) for Confirmation */ |
toddouska | 0:5045d2638c29 | 1371 | static int ConfirmSignature(DecodedCert* cert, const byte* key, word32 keySz, |
toddouska | 0:5045d2638c29 | 1372 | word32 keyOID) |
toddouska | 0:5045d2638c29 | 1373 | { |
toddouska | 0:5045d2638c29 | 1374 | byte digest[SHA_DIGEST_SIZE]; /* max size */ |
toddouska | 0:5045d2638c29 | 1375 | int hashType, digestSz, ret; |
toddouska | 0:5045d2638c29 | 1376 | |
toddouska | 0:5045d2638c29 | 1377 | if (cert->signatureOID == MD5wRSA) { |
toddouska | 0:5045d2638c29 | 1378 | Md5 md5; |
toddouska | 0:5045d2638c29 | 1379 | InitMd5(&md5); |
toddouska | 0:5045d2638c29 | 1380 | Md5Update(&md5, cert->source + cert->certBegin, |
toddouska | 0:5045d2638c29 | 1381 | cert->sigIndex - cert->certBegin); |
toddouska | 0:5045d2638c29 | 1382 | Md5Final(&md5, digest); |
toddouska | 0:5045d2638c29 | 1383 | hashType = MD5h; |
toddouska | 0:5045d2638c29 | 1384 | digestSz = MD5_DIGEST_SIZE; |
toddouska | 0:5045d2638c29 | 1385 | } |
toddouska | 0:5045d2638c29 | 1386 | else if (cert->signatureOID == SHAwRSA || cert->signatureOID == SHAwDSA) { |
toddouska | 0:5045d2638c29 | 1387 | Sha sha; |
toddouska | 0:5045d2638c29 | 1388 | InitSha(&sha); |
toddouska | 0:5045d2638c29 | 1389 | ShaUpdate(&sha, cert->source + cert->certBegin, |
toddouska | 0:5045d2638c29 | 1390 | cert->sigIndex - cert->certBegin); |
toddouska | 0:5045d2638c29 | 1391 | ShaFinal(&sha, digest); |
toddouska | 0:5045d2638c29 | 1392 | hashType = SHAh; |
toddouska | 0:5045d2638c29 | 1393 | digestSz = SHA_DIGEST_SIZE; |
toddouska | 0:5045d2638c29 | 1394 | } |
toddouska | 0:5045d2638c29 | 1395 | else |
toddouska | 0:5045d2638c29 | 1396 | return 0; /* ASN_SIG_HASH_E; */ |
toddouska | 0:5045d2638c29 | 1397 | |
toddouska | 0:5045d2638c29 | 1398 | if (keyOID == RSAk) { |
toddouska | 0:5045d2638c29 | 1399 | RsaKey pubKey; |
toddouska | 0:5045d2638c29 | 1400 | byte encodedSig[MAX_ENCODED_SIG_SZ]; |
toddouska | 0:5045d2638c29 | 1401 | byte plain[MAX_ENCODED_SIG_SZ]; |
toddouska | 0:5045d2638c29 | 1402 | word32 idx = 0; |
toddouska | 0:5045d2638c29 | 1403 | int sigSz, verifySz; |
toddouska | 0:5045d2638c29 | 1404 | byte* out; |
toddouska | 0:5045d2638c29 | 1405 | |
toddouska | 0:5045d2638c29 | 1406 | if (cert->sigLength > MAX_ENCODED_SIG_SZ) |
toddouska | 0:5045d2638c29 | 1407 | return 0; /* the key is too big */ |
toddouska | 0:5045d2638c29 | 1408 | |
toddouska | 0:5045d2638c29 | 1409 | InitRsaKey(&pubKey, cert->heap); |
toddouska | 0:5045d2638c29 | 1410 | if (RsaPublicKeyDecode(key, &idx, &pubKey, keySz) < 0) |
toddouska | 0:5045d2638c29 | 1411 | ret = 0; /* ASN_KEY_DECODE_E; */ |
toddouska | 0:5045d2638c29 | 1412 | |
toddouska | 0:5045d2638c29 | 1413 | else { |
toddouska | 0:5045d2638c29 | 1414 | XMEMCPY(plain, cert->signature, cert->sigLength); |
toddouska | 0:5045d2638c29 | 1415 | if ( (verifySz = RsaSSL_VerifyInline(plain, cert->sigLength, &out, |
toddouska | 0:5045d2638c29 | 1416 | &pubKey)) < 0) |
toddouska | 0:5045d2638c29 | 1417 | ret = 0; /* ASN_VERIFY_E; */ |
toddouska | 0:5045d2638c29 | 1418 | else { |
toddouska | 0:5045d2638c29 | 1419 | /* make sure we're right justified */ |
toddouska | 0:5045d2638c29 | 1420 | sigSz = EncodeSignature(encodedSig, digest, digestSz, hashType); |
toddouska | 0:5045d2638c29 | 1421 | if (sigSz != verifySz || XMEMCMP(out, encodedSig, sigSz) != 0) |
toddouska | 0:5045d2638c29 | 1422 | ret = 0; /* ASN_VERIFY_MATCH_E; */ |
toddouska | 0:5045d2638c29 | 1423 | else |
toddouska | 0:5045d2638c29 | 1424 | ret = 1; /* match */ |
toddouska | 0:5045d2638c29 | 1425 | } |
toddouska | 0:5045d2638c29 | 1426 | } |
toddouska | 0:5045d2638c29 | 1427 | FreeRsaKey(&pubKey); |
toddouska | 0:5045d2638c29 | 1428 | return ret; |
toddouska | 0:5045d2638c29 | 1429 | } |
toddouska | 0:5045d2638c29 | 1430 | else |
toddouska | 0:5045d2638c29 | 1431 | return 0; /* ASN_SIG_KEY_E; */ |
toddouska | 0:5045d2638c29 | 1432 | } |
toddouska | 0:5045d2638c29 | 1433 | |
toddouska | 0:5045d2638c29 | 1434 | |
toddouska | 0:5045d2638c29 | 1435 | int ParseCert(DecodedCert* cert, word32 inSz, int type, int verify, |
toddouska | 0:5045d2638c29 | 1436 | Signer* signers) |
toddouska | 0:5045d2638c29 | 1437 | { |
toddouska | 0:5045d2638c29 | 1438 | int ret; |
toddouska | 0:5045d2638c29 | 1439 | char* ptr; |
toddouska | 0:5045d2638c29 | 1440 | |
toddouska | 0:5045d2638c29 | 1441 | ret = ParseCertRelative(cert, inSz, type, verify, signers); |
toddouska | 0:5045d2638c29 | 1442 | if (ret < 0) |
toddouska | 0:5045d2638c29 | 1443 | return ret; |
toddouska | 0:5045d2638c29 | 1444 | |
toddouska | 0:5045d2638c29 | 1445 | if (cert->subjectCNLen > 0) { |
toddouska | 0:5045d2638c29 | 1446 | ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap, |
toddouska | 0:5045d2638c29 | 1447 | DYNAMIC_TYPE_SUBJECT_CN); |
toddouska | 0:5045d2638c29 | 1448 | if (ptr == NULL) |
toddouska | 0:5045d2638c29 | 1449 | return MEMORY_E; |
toddouska | 0:5045d2638c29 | 1450 | XMEMCPY(ptr, cert->subjectCN, cert->subjectCNLen); |
toddouska | 0:5045d2638c29 | 1451 | ptr[cert->subjectCNLen] = '\0'; |
toddouska | 0:5045d2638c29 | 1452 | cert->subjectCN = ptr; |
toddouska | 0:5045d2638c29 | 1453 | cert->subjectCNLen = 0; |
toddouska | 0:5045d2638c29 | 1454 | } |
toddouska | 0:5045d2638c29 | 1455 | |
toddouska | 0:5045d2638c29 | 1456 | if (cert->keyOID == RSAk && cert->pubKeySize > 0) { |
toddouska | 0:5045d2638c29 | 1457 | ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap, |
toddouska | 0:5045d2638c29 | 1458 | DYNAMIC_TYPE_PUBLIC_KEY); |
toddouska | 0:5045d2638c29 | 1459 | if (ptr == NULL) |
toddouska | 0:5045d2638c29 | 1460 | return MEMORY_E; |
toddouska | 0:5045d2638c29 | 1461 | XMEMCPY(ptr, cert->publicKey, cert->pubKeySize); |
toddouska | 0:5045d2638c29 | 1462 | cert->publicKey = (byte *)ptr; |
toddouska | 0:5045d2638c29 | 1463 | cert->pubKeyStored = 1; |
toddouska | 0:5045d2638c29 | 1464 | } |
toddouska | 0:5045d2638c29 | 1465 | |
toddouska | 0:5045d2638c29 | 1466 | return ret; |
toddouska | 0:5045d2638c29 | 1467 | } |
toddouska | 0:5045d2638c29 | 1468 | |
toddouska | 0:5045d2638c29 | 1469 | |
toddouska | 0:5045d2638c29 | 1470 | int ParseCertRelative(DecodedCert* cert, word32 inSz, int type, int verify, |
toddouska | 0:5045d2638c29 | 1471 | Signer* signers) |
toddouska | 0:5045d2638c29 | 1472 | { |
toddouska | 0:5045d2638c29 | 1473 | word32 confirmOID; |
toddouska | 0:5045d2638c29 | 1474 | int ret; |
toddouska | 0:5045d2638c29 | 1475 | int badDate = 0; |
toddouska | 0:5045d2638c29 | 1476 | int confirm = 0; |
toddouska | 0:5045d2638c29 | 1477 | |
toddouska | 0:5045d2638c29 | 1478 | if ((ret = DecodeToKey(cert, inSz, verify)) < 0) { |
toddouska | 0:5045d2638c29 | 1479 | if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) |
toddouska | 0:5045d2638c29 | 1480 | badDate = ret; |
toddouska | 0:5045d2638c29 | 1481 | else |
toddouska | 0:5045d2638c29 | 1482 | return ret; |
toddouska | 0:5045d2638c29 | 1483 | } |
toddouska | 0:5045d2638c29 | 1484 | |
toddouska | 0:5045d2638c29 | 1485 | if (cert->srcIdx != cert->sigIndex) |
toddouska | 0:5045d2638c29 | 1486 | cert->srcIdx = cert->sigIndex; |
toddouska | 0:5045d2638c29 | 1487 | |
toddouska | 0:5045d2638c29 | 1488 | if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID)) < 0) |
toddouska | 0:5045d2638c29 | 1489 | return ret; |
toddouska | 0:5045d2638c29 | 1490 | |
toddouska | 0:5045d2638c29 | 1491 | if ((ret = GetSignature(cert)) < 0) |
toddouska | 0:5045d2638c29 | 1492 | return ret; |
toddouska | 0:5045d2638c29 | 1493 | |
toddouska | 0:5045d2638c29 | 1494 | if (confirmOID != cert->signatureOID) |
toddouska | 0:5045d2638c29 | 1495 | return ASN_SIG_OID_E; |
toddouska | 0:5045d2638c29 | 1496 | |
toddouska | 0:5045d2638c29 | 1497 | if (verify && type != CA_TYPE) { |
toddouska | 0:5045d2638c29 | 1498 | while (signers) { |
toddouska | 0:5045d2638c29 | 1499 | if (XMEMCMP(cert->issuerHash, signers->hash, SHA_DIGEST_SIZE) |
toddouska | 0:5045d2638c29 | 1500 | == 0) { |
toddouska | 0:5045d2638c29 | 1501 | /* other confirm */ |
toddouska | 0:5045d2638c29 | 1502 | if (!ConfirmSignature(cert, signers->publicKey, |
toddouska | 0:5045d2638c29 | 1503 | signers->pubKeySize, signers->keyOID)) |
toddouska | 0:5045d2638c29 | 1504 | return ASN_SIG_CONFIRM_E; |
toddouska | 0:5045d2638c29 | 1505 | else { |
toddouska | 0:5045d2638c29 | 1506 | confirm = 1; |
toddouska | 0:5045d2638c29 | 1507 | break; |
toddouska | 0:5045d2638c29 | 1508 | } |
toddouska | 0:5045d2638c29 | 1509 | } |
toddouska | 0:5045d2638c29 | 1510 | signers = signers->next; |
toddouska | 0:5045d2638c29 | 1511 | } |
toddouska | 0:5045d2638c29 | 1512 | if (!confirm) |
toddouska | 0:5045d2638c29 | 1513 | return ASN_SIG_CONFIRM_E; |
toddouska | 0:5045d2638c29 | 1514 | } |
toddouska | 0:5045d2638c29 | 1515 | if (badDate != 0) |
toddouska | 0:5045d2638c29 | 1516 | return badDate; |
toddouska | 0:5045d2638c29 | 1517 | |
toddouska | 0:5045d2638c29 | 1518 | return 0; |
toddouska | 0:5045d2638c29 | 1519 | } |
toddouska | 0:5045d2638c29 | 1520 | |
toddouska | 0:5045d2638c29 | 1521 | |
toddouska | 0:5045d2638c29 | 1522 | Signer* MakeSigner(void* heap) |
toddouska | 0:5045d2638c29 | 1523 | { |
toddouska | 0:5045d2638c29 | 1524 | Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap, |
toddouska | 0:5045d2638c29 | 1525 | DYNAMIC_TYPE_SIGNER); |
toddouska | 0:5045d2638c29 | 1526 | if (signer) { |
toddouska | 0:5045d2638c29 | 1527 | signer->name = 0; |
toddouska | 0:5045d2638c29 | 1528 | signer->publicKey = 0; |
toddouska | 0:5045d2638c29 | 1529 | signer->next = 0; |
toddouska | 0:5045d2638c29 | 1530 | } |
toddouska | 0:5045d2638c29 | 1531 | |
toddouska | 0:5045d2638c29 | 1532 | return signer; |
toddouska | 0:5045d2638c29 | 1533 | } |
toddouska | 0:5045d2638c29 | 1534 | |
toddouska | 0:5045d2638c29 | 1535 | |
toddouska | 0:5045d2638c29 | 1536 | void FreeSigners(Signer* signer, void* heap) |
toddouska | 0:5045d2638c29 | 1537 | { |
toddouska | 0:5045d2638c29 | 1538 | Signer* next = signer; |
toddouska | 0:5045d2638c29 | 1539 | |
toddouska | 0:5045d2638c29 | 1540 | while( (signer = next) ) { |
toddouska | 0:5045d2638c29 | 1541 | next = signer->next; |
toddouska | 0:5045d2638c29 | 1542 | XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN); |
toddouska | 0:5045d2638c29 | 1543 | XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); |
toddouska | 0:5045d2638c29 | 1544 | XFREE(signer, heap, DYNAMIC_TYPE_SIGNER); |
toddouska | 0:5045d2638c29 | 1545 | } |
toddouska | 0:5045d2638c29 | 1546 | } |
toddouska | 0:5045d2638c29 | 1547 | |
toddouska | 0:5045d2638c29 | 1548 | |
toddouska | 0:5045d2638c29 | 1549 | void CTaoCryptErrorString(int error, char* buffer) |
toddouska | 0:5045d2638c29 | 1550 | { |
toddouska | 0:5045d2638c29 | 1551 | const int max = MAX_ERROR_SZ; /* shorthand */ |
toddouska | 0:5045d2638c29 | 1552 | |
toddouska | 0:5045d2638c29 | 1553 | #ifdef NO_ERROR_STRINGS |
toddouska | 0:5045d2638c29 | 1554 | |
toddouska | 0:5045d2638c29 | 1555 | XSTRNCPY(buffer, "no support for error strings built in", max); |
toddouska | 0:5045d2638c29 | 1556 | |
toddouska | 0:5045d2638c29 | 1557 | #else |
toddouska | 0:5045d2638c29 | 1558 | |
toddouska | 0:5045d2638c29 | 1559 | switch (error) { |
toddouska | 0:5045d2638c29 | 1560 | |
toddouska | 0:5045d2638c29 | 1561 | case OPEN_RAN_E : |
toddouska | 0:5045d2638c29 | 1562 | XSTRNCPY(buffer, "opening random device error", max); |
toddouska | 0:5045d2638c29 | 1563 | break; |
toddouska | 0:5045d2638c29 | 1564 | |
toddouska | 0:5045d2638c29 | 1565 | case READ_RAN_E : |
toddouska | 0:5045d2638c29 | 1566 | XSTRNCPY(buffer, "reading random device error", max); |
toddouska | 0:5045d2638c29 | 1567 | break; |
toddouska | 0:5045d2638c29 | 1568 | |
toddouska | 0:5045d2638c29 | 1569 | case WINCRYPT_E : |
toddouska | 0:5045d2638c29 | 1570 | XSTRNCPY(buffer, "windows crypt init error", max); |
toddouska | 0:5045d2638c29 | 1571 | break; |
toddouska | 0:5045d2638c29 | 1572 | |
toddouska | 0:5045d2638c29 | 1573 | case CRYPTGEN_E : |
toddouska | 0:5045d2638c29 | 1574 | XSTRNCPY(buffer, "windows crypt generation error", max); |
toddouska | 0:5045d2638c29 | 1575 | break; |
toddouska | 0:5045d2638c29 | 1576 | |
toddouska | 0:5045d2638c29 | 1577 | case RAN_BLOCK_E : |
toddouska | 0:5045d2638c29 | 1578 | XSTRNCPY(buffer, "random device read would block error", max); |
toddouska | 0:5045d2638c29 | 1579 | break; |
toddouska | 0:5045d2638c29 | 1580 | |
toddouska | 0:5045d2638c29 | 1581 | case MP_INIT_E : |
toddouska | 0:5045d2638c29 | 1582 | XSTRNCPY(buffer, "mp_init error state", max); |
toddouska | 0:5045d2638c29 | 1583 | break; |
toddouska | 0:5045d2638c29 | 1584 | |
toddouska | 0:5045d2638c29 | 1585 | case MP_READ_E : |
toddouska | 0:5045d2638c29 | 1586 | XSTRNCPY(buffer, "mp_read error state", max); |
toddouska | 0:5045d2638c29 | 1587 | break; |
toddouska | 0:5045d2638c29 | 1588 | |
toddouska | 0:5045d2638c29 | 1589 | case MP_EXPTMOD_E : |
toddouska | 0:5045d2638c29 | 1590 | XSTRNCPY(buffer, "mp_exptmod error state", max); |
toddouska | 0:5045d2638c29 | 1591 | break; |
toddouska | 0:5045d2638c29 | 1592 | |
toddouska | 0:5045d2638c29 | 1593 | case MP_TO_E : |
toddouska | 0:5045d2638c29 | 1594 | XSTRNCPY(buffer, "mp_to_xxx error state, can't convert", max); |
toddouska | 0:5045d2638c29 | 1595 | break; |
toddouska | 0:5045d2638c29 | 1596 | |
toddouska | 0:5045d2638c29 | 1597 | case MP_SUB_E : |
toddouska | 0:5045d2638c29 | 1598 | XSTRNCPY(buffer, "mp_sub error state, can't subtract", max); |
toddouska | 0:5045d2638c29 | 1599 | break; |
toddouska | 0:5045d2638c29 | 1600 | |
toddouska | 0:5045d2638c29 | 1601 | case MP_ADD_E : |
toddouska | 0:5045d2638c29 | 1602 | XSTRNCPY(buffer, "mp_add error state, can't add", max); |
toddouska | 0:5045d2638c29 | 1603 | break; |
toddouska | 0:5045d2638c29 | 1604 | |
toddouska | 0:5045d2638c29 | 1605 | case MP_MUL_E : |
toddouska | 0:5045d2638c29 | 1606 | XSTRNCPY(buffer, "mp_mul error state, can't multiply", max); |
toddouska | 0:5045d2638c29 | 1607 | break; |
toddouska | 0:5045d2638c29 | 1608 | |
toddouska | 0:5045d2638c29 | 1609 | case MP_MULMOD_E : |
toddouska | 0:5045d2638c29 | 1610 | XSTRNCPY(buffer, "mp_mulmod error state, can't multiply mod", max); |
toddouska | 0:5045d2638c29 | 1611 | break; |
toddouska | 0:5045d2638c29 | 1612 | |
toddouska | 0:5045d2638c29 | 1613 | case MP_MOD_E : |
toddouska | 0:5045d2638c29 | 1614 | XSTRNCPY(buffer, "mp_mod error state, can't mod", max); |
toddouska | 0:5045d2638c29 | 1615 | break; |
toddouska | 0:5045d2638c29 | 1616 | |
toddouska | 0:5045d2638c29 | 1617 | case MP_INVMOD_E : |
toddouska | 0:5045d2638c29 | 1618 | XSTRNCPY(buffer, "mp_invmod error state, can't inv mod", max); |
toddouska | 0:5045d2638c29 | 1619 | break; |
toddouska | 0:5045d2638c29 | 1620 | |
toddouska | 0:5045d2638c29 | 1621 | case MP_CMP_E : |
toddouska | 0:5045d2638c29 | 1622 | XSTRNCPY(buffer, "mp_cmp error state", max); |
toddouska | 0:5045d2638c29 | 1623 | break; |
toddouska | 0:5045d2638c29 | 1624 | |
toddouska | 0:5045d2638c29 | 1625 | case MEMORY_E : |
toddouska | 0:5045d2638c29 | 1626 | XSTRNCPY(buffer, "out of memory error", max); |
toddouska | 0:5045d2638c29 | 1627 | break; |
toddouska | 0:5045d2638c29 | 1628 | |
toddouska | 0:5045d2638c29 | 1629 | case RSA_WRONG_TYPE_E : |
toddouska | 0:5045d2638c29 | 1630 | XSTRNCPY(buffer, "RSA wrong block type for RSA function", max); |
toddouska | 0:5045d2638c29 | 1631 | break; |
toddouska | 0:5045d2638c29 | 1632 | |
toddouska | 0:5045d2638c29 | 1633 | case RSA_BUFFER_E : |
toddouska | 0:5045d2638c29 | 1634 | XSTRNCPY(buffer, "RSA buffer error, output too small or input too big", |
toddouska | 0:5045d2638c29 | 1635 | max); |
toddouska | 0:5045d2638c29 | 1636 | break; |
toddouska | 0:5045d2638c29 | 1637 | |
toddouska | 0:5045d2638c29 | 1638 | case BUFFER_E : |
toddouska | 0:5045d2638c29 | 1639 | XSTRNCPY(buffer, "Buffer error, output too small or input too big", max); |
toddouska | 0:5045d2638c29 | 1640 | break; |
toddouska | 0:5045d2638c29 | 1641 | |
toddouska | 0:5045d2638c29 | 1642 | case ALGO_ID_E : |
toddouska | 0:5045d2638c29 | 1643 | XSTRNCPY(buffer, "Setting Cert AlogID error", max); |
toddouska | 0:5045d2638c29 | 1644 | break; |
toddouska | 0:5045d2638c29 | 1645 | |
toddouska | 0:5045d2638c29 | 1646 | case PUBLIC_KEY_E : |
toddouska | 0:5045d2638c29 | 1647 | XSTRNCPY(buffer, "Setting Cert Public Key error", max); |
toddouska | 0:5045d2638c29 | 1648 | break; |
toddouska | 0:5045d2638c29 | 1649 | |
toddouska | 0:5045d2638c29 | 1650 | case DATE_E : |
toddouska | 0:5045d2638c29 | 1651 | XSTRNCPY(buffer, "Setting Cert Date validity error", max); |
toddouska | 0:5045d2638c29 | 1652 | break; |
toddouska | 0:5045d2638c29 | 1653 | |
toddouska | 0:5045d2638c29 | 1654 | case SUBJECT_E : |
toddouska | 0:5045d2638c29 | 1655 | XSTRNCPY(buffer, "Setting Cert Subject name error", max); |
toddouska | 0:5045d2638c29 | 1656 | break; |
toddouska | 0:5045d2638c29 | 1657 | |
toddouska | 0:5045d2638c29 | 1658 | case ISSUER_E : |
toddouska | 0:5045d2638c29 | 1659 | XSTRNCPY(buffer, "Setting Cert Issuer name error", max); |
toddouska | 0:5045d2638c29 | 1660 | break; |
toddouska | 0:5045d2638c29 | 1661 | |
toddouska | 0:5045d2638c29 | 1662 | case ASN_PARSE_E : |
toddouska | 0:5045d2638c29 | 1663 | XSTRNCPY(buffer, "ASN parsing error, invalid input", max); |
toddouska | 0:5045d2638c29 | 1664 | break; |
toddouska | 0:5045d2638c29 | 1665 | |
toddouska | 0:5045d2638c29 | 1666 | case ASN_VERSION_E : |
toddouska | 0:5045d2638c29 | 1667 | XSTRNCPY(buffer, "ASN version error, invalid number", max); |
toddouska | 0:5045d2638c29 | 1668 | break; |
toddouska | 0:5045d2638c29 | 1669 | |
toddouska | 0:5045d2638c29 | 1670 | case ASN_GETINT_E : |
toddouska | 0:5045d2638c29 | 1671 | XSTRNCPY(buffer, "ASN get big int error, invalid data", max); |
toddouska | 0:5045d2638c29 | 1672 | break; |
toddouska | 0:5045d2638c29 | 1673 | |
toddouska | 0:5045d2638c29 | 1674 | case ASN_RSA_KEY_E : |
toddouska | 0:5045d2638c29 | 1675 | XSTRNCPY(buffer, "ASN key init error, invalid input", max); |
toddouska | 0:5045d2638c29 | 1676 | break; |
toddouska | 0:5045d2638c29 | 1677 | |
toddouska | 0:5045d2638c29 | 1678 | case ASN_OBJECT_ID_E : |
toddouska | 0:5045d2638c29 | 1679 | XSTRNCPY(buffer, "ASN object id error, invalid id", max); |
toddouska | 0:5045d2638c29 | 1680 | break; |
toddouska | 0:5045d2638c29 | 1681 | |
toddouska | 0:5045d2638c29 | 1682 | case ASN_TAG_NULL_E : |
toddouska | 0:5045d2638c29 | 1683 | XSTRNCPY(buffer, "ASN tag error, not null", max); |
toddouska | 0:5045d2638c29 | 1684 | break; |
toddouska | 0:5045d2638c29 | 1685 | |
toddouska | 0:5045d2638c29 | 1686 | case ASN_EXPECT_0_E : |
toddouska | 0:5045d2638c29 | 1687 | XSTRNCPY(buffer, "ASN expect error, not zero", max); |
toddouska | 0:5045d2638c29 | 1688 | break; |
toddouska | 0:5045d2638c29 | 1689 | |
toddouska | 0:5045d2638c29 | 1690 | case ASN_BITSTR_E : |
toddouska | 0:5045d2638c29 | 1691 | XSTRNCPY(buffer, "ASN bit string error, wrong id", max); |
toddouska | 0:5045d2638c29 | 1692 | break; |
toddouska | 0:5045d2638c29 | 1693 | |
toddouska | 0:5045d2638c29 | 1694 | case ASN_UNKNOWN_OID_E : |
toddouska | 0:5045d2638c29 | 1695 | XSTRNCPY(buffer, "ASN oid error, unknown sum id", max); |
toddouska | 0:5045d2638c29 | 1696 | break; |
toddouska | 0:5045d2638c29 | 1697 | |
toddouska | 0:5045d2638c29 | 1698 | case ASN_DATE_SZ_E : |
toddouska | 0:5045d2638c29 | 1699 | XSTRNCPY(buffer, "ASN date error, bad size", max); |
toddouska | 0:5045d2638c29 | 1700 | break; |
toddouska | 0:5045d2638c29 | 1701 | |
toddouska | 0:5045d2638c29 | 1702 | case ASN_BEFORE_DATE_E : |
toddouska | 0:5045d2638c29 | 1703 | XSTRNCPY(buffer, "ASN date error, current date before", max); |
toddouska | 0:5045d2638c29 | 1704 | break; |
toddouska | 0:5045d2638c29 | 1705 | |
toddouska | 0:5045d2638c29 | 1706 | case ASN_AFTER_DATE_E : |
toddouska | 0:5045d2638c29 | 1707 | XSTRNCPY(buffer, "ASN date error, current date after", max); |
toddouska | 0:5045d2638c29 | 1708 | break; |
toddouska | 0:5045d2638c29 | 1709 | |
toddouska | 0:5045d2638c29 | 1710 | case ASN_SIG_OID_E : |
toddouska | 0:5045d2638c29 | 1711 | XSTRNCPY(buffer, "ASN signature error, mismatched oid", max); |
toddouska | 0:5045d2638c29 | 1712 | break; |
toddouska | 0:5045d2638c29 | 1713 | |
toddouska | 0:5045d2638c29 | 1714 | case ASN_TIME_E : |
toddouska | 0:5045d2638c29 | 1715 | XSTRNCPY(buffer, "ASN time error, unkown time type", max); |
toddouska | 0:5045d2638c29 | 1716 | break; |
toddouska | 0:5045d2638c29 | 1717 | |
toddouska | 0:5045d2638c29 | 1718 | case ASN_INPUT_E : |
toddouska | 0:5045d2638c29 | 1719 | XSTRNCPY(buffer, "ASN input error, not enough data", max); |
toddouska | 0:5045d2638c29 | 1720 | break; |
toddouska | 0:5045d2638c29 | 1721 | |
toddouska | 0:5045d2638c29 | 1722 | case ASN_SIG_CONFIRM_E : |
toddouska | 0:5045d2638c29 | 1723 | XSTRNCPY(buffer, "ASN sig error, confirm failure", max); |
toddouska | 0:5045d2638c29 | 1724 | break; |
toddouska | 0:5045d2638c29 | 1725 | |
toddouska | 0:5045d2638c29 | 1726 | case ASN_SIG_HASH_E : |
toddouska | 0:5045d2638c29 | 1727 | XSTRNCPY(buffer, "ASN sig error, unsupported hash type", max); |
toddouska | 0:5045d2638c29 | 1728 | break; |
toddouska | 0:5045d2638c29 | 1729 | |
toddouska | 0:5045d2638c29 | 1730 | case ASN_SIG_KEY_E : |
toddouska | 0:5045d2638c29 | 1731 | XSTRNCPY(buffer, "ASN sig error, unsupported key type", max); |
toddouska | 0:5045d2638c29 | 1732 | break; |
toddouska | 0:5045d2638c29 | 1733 | |
toddouska | 0:5045d2638c29 | 1734 | case ASN_DH_KEY_E : |
toddouska | 0:5045d2638c29 | 1735 | XSTRNCPY(buffer, "ASN key init error, invalid input", max); |
toddouska | 0:5045d2638c29 | 1736 | break; |
toddouska | 0:5045d2638c29 | 1737 | |
toddouska | 0:5045d2638c29 | 1738 | case ASN_NTRU_KEY_E : |
toddouska | 0:5045d2638c29 | 1739 | XSTRNCPY(buffer, "ASN NTRU key decode error, invalid input", max); |
toddouska | 0:5045d2638c29 | 1740 | break; |
toddouska | 0:5045d2638c29 | 1741 | |
toddouska | 0:5045d2638c29 | 1742 | default: |
toddouska | 0:5045d2638c29 | 1743 | XSTRNCPY(buffer, "unknown error number", max); |
toddouska | 0:5045d2638c29 | 1744 | |
toddouska | 0:5045d2638c29 | 1745 | } |
toddouska | 0:5045d2638c29 | 1746 | |
toddouska | 0:5045d2638c29 | 1747 | #endif /* NO_ERROR_STRINGS */ |
toddouska | 0:5045d2638c29 | 1748 | |
toddouska | 0:5045d2638c29 | 1749 | } |
toddouska | 0:5045d2638c29 | 1750 | |
toddouska | 0:5045d2638c29 | 1751 | |
toddouska | 0:5045d2638c29 | 1752 | #if defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) |
toddouska | 0:5045d2638c29 | 1753 | |
toddouska | 0:5045d2638c29 | 1754 | static int SetMyVersion(word32 version, byte* output, int header) |
toddouska | 0:5045d2638c29 | 1755 | { |
toddouska | 0:5045d2638c29 | 1756 | int i = 0; |
toddouska | 0:5045d2638c29 | 1757 | |
toddouska | 0:5045d2638c29 | 1758 | if (header) { |
toddouska | 0:5045d2638c29 | 1759 | output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; |
toddouska | 0:5045d2638c29 | 1760 | output[i++] = ASN_BIT_STRING; |
toddouska | 0:5045d2638c29 | 1761 | } |
toddouska | 0:5045d2638c29 | 1762 | output[i++] = ASN_INTEGER; |
toddouska | 0:5045d2638c29 | 1763 | output[i++] = 0x01; |
toddouska | 0:5045d2638c29 | 1764 | output[i++] = version; |
toddouska | 0:5045d2638c29 | 1765 | |
toddouska | 0:5045d2638c29 | 1766 | return i; |
toddouska | 0:5045d2638c29 | 1767 | } |
toddouska | 0:5045d2638c29 | 1768 | |
toddouska | 0:5045d2638c29 | 1769 | |
toddouska | 0:5045d2638c29 | 1770 | int DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz, |
toddouska | 0:5045d2638c29 | 1771 | int type) |
toddouska | 0:5045d2638c29 | 1772 | { |
toddouska | 0:5045d2638c29 | 1773 | char header[80]; |
toddouska | 0:5045d2638c29 | 1774 | char footer[80]; |
toddouska | 0:5045d2638c29 | 1775 | |
toddouska | 0:5045d2638c29 | 1776 | int headerLen; |
toddouska | 0:5045d2638c29 | 1777 | int footerLen; |
toddouska | 0:5045d2638c29 | 1778 | int i; |
toddouska | 0:5045d2638c29 | 1779 | int outLen; /* return length or error */ |
toddouska | 0:5045d2638c29 | 1780 | |
toddouska | 0:5045d2638c29 | 1781 | if (type == CERT_TYPE) { |
toddouska | 0:5045d2638c29 | 1782 | XSTRNCPY(header, "-----BEGIN CERTIFICATE-----\n", sizeof(header)); |
toddouska | 0:5045d2638c29 | 1783 | XSTRNCPY(footer, "-----END CERTIFICATE-----\n", sizeof(footer)); |
toddouska | 0:5045d2638c29 | 1784 | } else { |
toddouska | 0:5045d2638c29 | 1785 | XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----\n", sizeof(header)); |
toddouska | 0:5045d2638c29 | 1786 | XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----\n", sizeof(footer)); |
toddouska | 0:5045d2638c29 | 1787 | } |
toddouska | 0:5045d2638c29 | 1788 | |
toddouska | 0:5045d2638c29 | 1789 | headerLen = XSTRLEN(header); |
toddouska | 0:5045d2638c29 | 1790 | footerLen = XSTRLEN(footer); |
toddouska | 0:5045d2638c29 | 1791 | |
toddouska | 0:5045d2638c29 | 1792 | if (!der || !output) |
toddouska | 0:5045d2638c29 | 1793 | return -1; |
toddouska | 0:5045d2638c29 | 1794 | |
toddouska | 0:5045d2638c29 | 1795 | /* don't even try if outSz too short */ |
toddouska | 0:5045d2638c29 | 1796 | if (outSz < headerLen + footerLen + derSz) |
toddouska | 0:5045d2638c29 | 1797 | return -1; |
toddouska | 0:5045d2638c29 | 1798 | |
toddouska | 0:5045d2638c29 | 1799 | /* header */ |
toddouska | 0:5045d2638c29 | 1800 | XMEMCPY(output, header, headerLen); |
toddouska | 0:5045d2638c29 | 1801 | i = headerLen; |
toddouska | 0:5045d2638c29 | 1802 | |
toddouska | 0:5045d2638c29 | 1803 | /* body */ |
toddouska | 0:5045d2638c29 | 1804 | outLen = outSz; /* input to Base64Encode */ |
toddouska | 0:5045d2638c29 | 1805 | if (Base64Encode(der, derSz, output + i, (word32*)&outLen) < 0) |
toddouska | 0:5045d2638c29 | 1806 | return -1; |
toddouska | 0:5045d2638c29 | 1807 | i += outLen; |
toddouska | 0:5045d2638c29 | 1808 | |
toddouska | 0:5045d2638c29 | 1809 | /* footer */ |
toddouska | 0:5045d2638c29 | 1810 | if ( (i + footerLen) > (int)outSz) |
toddouska | 0:5045d2638c29 | 1811 | return -1; |
toddouska | 0:5045d2638c29 | 1812 | XMEMCPY(output + i, footer, footerLen); |
toddouska | 0:5045d2638c29 | 1813 | |
toddouska | 0:5045d2638c29 | 1814 | return outLen + headerLen + footerLen; |
toddouska | 0:5045d2638c29 | 1815 | } |
toddouska | 0:5045d2638c29 | 1816 | |
toddouska | 0:5045d2638c29 | 1817 | |
toddouska | 0:5045d2638c29 | 1818 | #endif /* CYASSL_KEY_GEN || CYASSL_CERT_GEN */ |
toddouska | 0:5045d2638c29 | 1819 | |
toddouska | 0:5045d2638c29 | 1820 | |
toddouska | 0:5045d2638c29 | 1821 | #ifdef CYASSL_KEY_GEN |
toddouska | 0:5045d2638c29 | 1822 | |
toddouska | 0:5045d2638c29 | 1823 | |
toddouska | 0:5045d2638c29 | 1824 | static mp_int* GetRsaInt(RsaKey* key, int index) |
toddouska | 0:5045d2638c29 | 1825 | { |
toddouska | 0:5045d2638c29 | 1826 | if (index == 0) |
toddouska | 0:5045d2638c29 | 1827 | return &key->n; |
toddouska | 0:5045d2638c29 | 1828 | if (index == 1) |
toddouska | 0:5045d2638c29 | 1829 | return &key->e; |
toddouska | 0:5045d2638c29 | 1830 | if (index == 2) |
toddouska | 0:5045d2638c29 | 1831 | return &key->d; |
toddouska | 0:5045d2638c29 | 1832 | if (index == 3) |
toddouska | 0:5045d2638c29 | 1833 | return &key->p; |
toddouska | 0:5045d2638c29 | 1834 | if (index == 4) |
toddouska | 0:5045d2638c29 | 1835 | return &key->q; |
toddouska | 0:5045d2638c29 | 1836 | if (index == 5) |
toddouska | 0:5045d2638c29 | 1837 | return &key->dP; |
toddouska | 0:5045d2638c29 | 1838 | if (index == 6) |
toddouska | 0:5045d2638c29 | 1839 | return &key->dQ; |
toddouska | 0:5045d2638c29 | 1840 | if (index == 7) |
toddouska | 0:5045d2638c29 | 1841 | return &key->u; |
toddouska | 0:5045d2638c29 | 1842 | |
toddouska | 0:5045d2638c29 | 1843 | return NULL; |
toddouska | 0:5045d2638c29 | 1844 | } |
toddouska | 0:5045d2638c29 | 1845 | |
toddouska | 0:5045d2638c29 | 1846 | |
toddouska | 0:5045d2638c29 | 1847 | /* Convert RsaKey key to DER format, write to output (inLen), return bytes |
toddouska | 0:5045d2638c29 | 1848 | written */ |
toddouska | 0:5045d2638c29 | 1849 | int RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) |
toddouska | 0:5045d2638c29 | 1850 | { |
toddouska | 0:5045d2638c29 | 1851 | word32 seqSz, verSz, rawLen, intTotalLen = 0; |
toddouska | 0:5045d2638c29 | 1852 | word32 sizes[RSA_INTS]; |
toddouska | 0:5045d2638c29 | 1853 | int i, j, outLen; |
toddouska | 0:5045d2638c29 | 1854 | |
toddouska | 0:5045d2638c29 | 1855 | byte seq[MAX_SEQ_SZ]; |
toddouska | 0:5045d2638c29 | 1856 | byte ver[MAX_VERSION_SZ]; |
toddouska | 0:5045d2638c29 | 1857 | byte tmps[RSA_INTS][MAX_RSA_INT_SZ]; |
toddouska | 0:5045d2638c29 | 1858 | |
toddouska | 0:5045d2638c29 | 1859 | if (!key || !output) |
toddouska | 0:5045d2638c29 | 1860 | return -1; |
toddouska | 0:5045d2638c29 | 1861 | |
toddouska | 0:5045d2638c29 | 1862 | if (key->type != RSA_PRIVATE) |
toddouska | 0:5045d2638c29 | 1863 | return -1; |
toddouska | 0:5045d2638c29 | 1864 | |
toddouska | 0:5045d2638c29 | 1865 | /* write all big ints from key to DER tmps */ |
toddouska | 0:5045d2638c29 | 1866 | for (i = 0; i < RSA_INTS; i++) { |
toddouska | 0:5045d2638c29 | 1867 | mp_int* keyInt = GetRsaInt(key, i); |
toddouska | 0:5045d2638c29 | 1868 | rawLen = mp_unsigned_bin_size(keyInt); |
toddouska | 0:5045d2638c29 | 1869 | |
toddouska | 0:5045d2638c29 | 1870 | tmps[i][0] = ASN_INTEGER; |
toddouska | 0:5045d2638c29 | 1871 | sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1; /* int tag */ |
toddouska | 0:5045d2638c29 | 1872 | |
toddouska | 0:5045d2638c29 | 1873 | if ( (sizes[i] + rawLen) < sizeof(tmps[i])) { |
toddouska | 0:5045d2638c29 | 1874 | int err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); |
toddouska | 0:5045d2638c29 | 1875 | if (err == MP_OKAY) { |
toddouska | 0:5045d2638c29 | 1876 | sizes[i] += rawLen; |
toddouska | 0:5045d2638c29 | 1877 | intTotalLen += sizes[i]; |
toddouska | 0:5045d2638c29 | 1878 | } |
toddouska | 0:5045d2638c29 | 1879 | else |
toddouska | 0:5045d2638c29 | 1880 | return err; |
toddouska | 0:5045d2638c29 | 1881 | } |
toddouska | 0:5045d2638c29 | 1882 | else |
toddouska | 0:5045d2638c29 | 1883 | return -1; |
toddouska | 0:5045d2638c29 | 1884 | } |
toddouska | 0:5045d2638c29 | 1885 | |
toddouska | 0:5045d2638c29 | 1886 | /* make headers */ |
toddouska | 0:5045d2638c29 | 1887 | verSz = SetMyVersion(0, ver, FALSE); |
toddouska | 0:5045d2638c29 | 1888 | seqSz = SetSequence(verSz + intTotalLen, seq); |
toddouska | 0:5045d2638c29 | 1889 | |
toddouska | 0:5045d2638c29 | 1890 | outLen = seqSz + verSz + intTotalLen; |
toddouska | 0:5045d2638c29 | 1891 | if (outLen > (int)inLen) |
toddouska | 0:5045d2638c29 | 1892 | return -1; |
toddouska | 0:5045d2638c29 | 1893 | |
toddouska | 0:5045d2638c29 | 1894 | /* write to output */ |
toddouska | 0:5045d2638c29 | 1895 | XMEMCPY(output, seq, seqSz); |
toddouska | 0:5045d2638c29 | 1896 | j = seqSz; |
toddouska | 0:5045d2638c29 | 1897 | XMEMCPY(output + j, ver, verSz); |
toddouska | 0:5045d2638c29 | 1898 | j += verSz; |
toddouska | 0:5045d2638c29 | 1899 | |
toddouska | 0:5045d2638c29 | 1900 | for (i = 0; i < RSA_INTS; i++) { |
toddouska | 0:5045d2638c29 | 1901 | XMEMCPY(output + j, tmps[i], sizes[i]); |
toddouska | 0:5045d2638c29 | 1902 | j += sizes[i]; |
toddouska | 0:5045d2638c29 | 1903 | } |
toddouska | 0:5045d2638c29 | 1904 | |
toddouska | 0:5045d2638c29 | 1905 | return outLen; |
toddouska | 0:5045d2638c29 | 1906 | } |
toddouska | 0:5045d2638c29 | 1907 | |
toddouska | 0:5045d2638c29 | 1908 | #endif /* CYASSL_KEY_GEN */ |
toddouska | 0:5045d2638c29 | 1909 | |
toddouska | 0:5045d2638c29 | 1910 | |
toddouska | 0:5045d2638c29 | 1911 | #ifdef CYASSL_CERT_GEN |
toddouska | 0:5045d2638c29 | 1912 | |
toddouska | 0:5045d2638c29 | 1913 | /* Initialize and Set Certficate defaults: |
toddouska | 0:5045d2638c29 | 1914 | version = 3 (0x2) |
toddouska | 0:5045d2638c29 | 1915 | serial = 0 |
toddouska | 0:5045d2638c29 | 1916 | sigType = MD5_WITH_RSA |
toddouska | 0:5045d2638c29 | 1917 | issuer = blank |
toddouska | 0:5045d2638c29 | 1918 | daysValid = 500 |
toddouska | 0:5045d2638c29 | 1919 | selfSigned = 1 (true) use subject as issuer |
toddouska | 0:5045d2638c29 | 1920 | subject = blank |
toddouska | 0:5045d2638c29 | 1921 | */ |
toddouska | 0:5045d2638c29 | 1922 | void InitCert(Cert* cert) |
toddouska | 0:5045d2638c29 | 1923 | { |
toddouska | 0:5045d2638c29 | 1924 | cert->version = 2; /* version 3 is hex 2 */ |
toddouska | 0:5045d2638c29 | 1925 | cert->sigType = MD5wRSA; |
toddouska | 0:5045d2638c29 | 1926 | cert->daysValid = 500; |
toddouska | 0:5045d2638c29 | 1927 | cert->selfSigned = 1; |
toddouska | 0:5045d2638c29 | 1928 | cert->bodySz = 0; |
toddouska | 0:5045d2638c29 | 1929 | cert->keyType = RSA_KEY; |
toddouska | 0:5045d2638c29 | 1930 | XMEMSET(cert->serial, 0, SERIAL_SIZE); |
toddouska | 0:5045d2638c29 | 1931 | |
toddouska | 0:5045d2638c29 | 1932 | cert->issuer.country[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1933 | cert->issuer.state[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1934 | cert->issuer.locality[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1935 | cert->issuer.sur[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1936 | cert->issuer.org[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1937 | cert->issuer.unit[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1938 | cert->issuer.commonName[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1939 | cert->issuer.email[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1940 | |
toddouska | 0:5045d2638c29 | 1941 | cert->subject.country[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1942 | cert->subject.state[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1943 | cert->subject.locality[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1944 | cert->subject.sur[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1945 | cert->subject.org[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1946 | cert->subject.unit[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1947 | cert->subject.commonName[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1948 | cert->subject.email[0] = '\0'; |
toddouska | 0:5045d2638c29 | 1949 | } |
toddouska | 0:5045d2638c29 | 1950 | |
toddouska | 0:5045d2638c29 | 1951 | |
toddouska | 0:5045d2638c29 | 1952 | /* DER encoded x509 Certificate */ |
toddouska | 0:5045d2638c29 | 1953 | typedef struct DerCert { |
toddouska | 0:5045d2638c29 | 1954 | byte size[MAX_LENGTH_SZ]; /* length encoded */ |
toddouska | 0:5045d2638c29 | 1955 | byte version[MAX_VERSION_SZ]; /* version encoded */ |
toddouska | 0:5045d2638c29 | 1956 | byte serial[SERIAL_SIZE + MAX_LENGTH_SZ]; /* serial number encoded */ |
toddouska | 0:5045d2638c29 | 1957 | byte sigAlgo[MAX_ALGO_SZ]; /* signature algo encoded */ |
toddouska | 0:5045d2638c29 | 1958 | byte issuer[ASN_NAME_MAX]; /* issuer encoded */ |
toddouska | 0:5045d2638c29 | 1959 | byte subject[ASN_NAME_MAX]; /* subject encoded */ |
toddouska | 0:5045d2638c29 | 1960 | byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */ |
toddouska | 0:5045d2638c29 | 1961 | byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */ |
toddouska | 0:5045d2638c29 | 1962 | int sizeSz; /* encoded size length */ |
toddouska | 0:5045d2638c29 | 1963 | int versionSz; /* encoded version length */ |
toddouska | 0:5045d2638c29 | 1964 | int serialSz; /* encoded serial length */ |
toddouska | 0:5045d2638c29 | 1965 | int sigAlgoSz; /* enocded sig alog length */ |
toddouska | 0:5045d2638c29 | 1966 | int issuerSz; /* encoded issuer length */ |
toddouska | 0:5045d2638c29 | 1967 | int subjectSz; /* encoded subject length */ |
toddouska | 0:5045d2638c29 | 1968 | int validitySz; /* encoded validity length */ |
toddouska | 0:5045d2638c29 | 1969 | int publicKeySz; /* encoded public key length */ |
toddouska | 0:5045d2638c29 | 1970 | int total; /* total encoded lengths */ |
toddouska | 0:5045d2638c29 | 1971 | } DerCert; |
toddouska | 0:5045d2638c29 | 1972 | |
toddouska | 0:5045d2638c29 | 1973 | |
toddouska | 0:5045d2638c29 | 1974 | /* Write a set header to output */ |
toddouska | 0:5045d2638c29 | 1975 | static word32 SetSet(word32 len, byte* output) |
toddouska | 0:5045d2638c29 | 1976 | { |
toddouska | 0:5045d2638c29 | 1977 | output[0] = ASN_SET | ASN_CONSTRUCTED; |
toddouska | 0:5045d2638c29 | 1978 | return SetLength(len, output + 1) + 1; |
toddouska | 0:5045d2638c29 | 1979 | } |
toddouska | 0:5045d2638c29 | 1980 | |
toddouska | 0:5045d2638c29 | 1981 | |
toddouska | 0:5045d2638c29 | 1982 | /* Write a serial number to output */ |
toddouska | 0:5045d2638c29 | 1983 | static int SetSerial(const byte* serial, byte* output) |
toddouska | 0:5045d2638c29 | 1984 | { |
toddouska | 0:5045d2638c29 | 1985 | int length = 0; |
toddouska | 0:5045d2638c29 | 1986 | |
toddouska | 0:5045d2638c29 | 1987 | output[length++] = ASN_INTEGER; |
toddouska | 0:5045d2638c29 | 1988 | length += SetLength(SERIAL_SIZE, &output[length]); |
toddouska | 0:5045d2638c29 | 1989 | XMEMCPY(&output[length], serial, SERIAL_SIZE); |
toddouska | 0:5045d2638c29 | 1990 | |
toddouska | 0:5045d2638c29 | 1991 | return length + SERIAL_SIZE; |
toddouska | 0:5045d2638c29 | 1992 | } |
toddouska | 0:5045d2638c29 | 1993 | |
toddouska | 0:5045d2638c29 | 1994 | |
toddouska | 0:5045d2638c29 | 1995 | /* Write a public RSA key to output */ |
toddouska | 0:5045d2638c29 | 1996 | static int SetPublicKey(byte* output, RsaKey* key) |
toddouska | 0:5045d2638c29 | 1997 | { |
toddouska | 0:5045d2638c29 | 1998 | byte n[MAX_RSA_INT_SZ]; |
toddouska | 0:5045d2638c29 | 1999 | byte e[MAX_RSA_E_SZ]; |
toddouska | 0:5045d2638c29 | 2000 | byte algo[MAX_ALGO_SZ]; |
toddouska | 0:5045d2638c29 | 2001 | byte seq[MAX_SEQ_SZ]; |
toddouska | 0:5045d2638c29 | 2002 | byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ |
toddouska | 0:5045d2638c29 | 2003 | int nSz; |
toddouska | 0:5045d2638c29 | 2004 | int eSz; |
toddouska | 0:5045d2638c29 | 2005 | int algoSz; |
toddouska | 0:5045d2638c29 | 2006 | int seqSz; |
toddouska | 0:5045d2638c29 | 2007 | int lenSz; |
toddouska | 0:5045d2638c29 | 2008 | int idx; |
toddouska | 0:5045d2638c29 | 2009 | int rawLen; |
toddouska | 0:5045d2638c29 | 2010 | |
toddouska | 0:5045d2638c29 | 2011 | /* n */ |
toddouska | 0:5045d2638c29 | 2012 | rawLen = mp_unsigned_bin_size(&key->n); |
toddouska | 0:5045d2638c29 | 2013 | n[0] = ASN_INTEGER; |
toddouska | 0:5045d2638c29 | 2014 | nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ |
toddouska | 0:5045d2638c29 | 2015 | |
toddouska | 0:5045d2638c29 | 2016 | if ( (nSz + rawLen) < sizeof(n)) { |
toddouska | 0:5045d2638c29 | 2017 | int err = mp_to_unsigned_bin(&key->n, n + nSz); |
toddouska | 0:5045d2638c29 | 2018 | if (err == MP_OKAY) |
toddouska | 0:5045d2638c29 | 2019 | nSz += rawLen; |
toddouska | 0:5045d2638c29 | 2020 | else |
toddouska | 0:5045d2638c29 | 2021 | return MP_TO_E; |
toddouska | 0:5045d2638c29 | 2022 | } |
toddouska | 0:5045d2638c29 | 2023 | else |
toddouska | 0:5045d2638c29 | 2024 | return BUFFER_E; |
toddouska | 0:5045d2638c29 | 2025 | |
toddouska | 0:5045d2638c29 | 2026 | /* e */ |
toddouska | 0:5045d2638c29 | 2027 | rawLen = mp_unsigned_bin_size(&key->e); |
toddouska | 0:5045d2638c29 | 2028 | e[0] = ASN_INTEGER; |
toddouska | 0:5045d2638c29 | 2029 | eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ |
toddouska | 0:5045d2638c29 | 2030 | |
toddouska | 0:5045d2638c29 | 2031 | if ( (eSz + rawLen) < sizeof(e)) { |
toddouska | 0:5045d2638c29 | 2032 | int err = mp_to_unsigned_bin(&key->e, e + eSz); |
toddouska | 0:5045d2638c29 | 2033 | if (err == MP_OKAY) |
toddouska | 0:5045d2638c29 | 2034 | eSz += rawLen; |
toddouska | 0:5045d2638c29 | 2035 | else |
toddouska | 0:5045d2638c29 | 2036 | return MP_TO_E; |
toddouska | 0:5045d2638c29 | 2037 | } |
toddouska | 0:5045d2638c29 | 2038 | else |
toddouska | 0:5045d2638c29 | 2039 | return BUFFER_E; |
toddouska | 0:5045d2638c29 | 2040 | |
toddouska | 0:5045d2638c29 | 2041 | /* headers */ |
toddouska | 0:5045d2638c29 | 2042 | algoSz = SetAlgoID(RSAk, algo, keyType); |
toddouska | 0:5045d2638c29 | 2043 | seqSz = SetSequence(nSz + eSz, seq); |
toddouska | 0:5045d2638c29 | 2044 | lenSz = SetLength(seqSz + nSz + eSz + 1, len); |
toddouska | 0:5045d2638c29 | 2045 | len[lenSz++] = 0; /* trailing 0 */ |
toddouska | 0:5045d2638c29 | 2046 | |
toddouska | 0:5045d2638c29 | 2047 | /* write */ |
toddouska | 0:5045d2638c29 | 2048 | idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); |
toddouska | 0:5045d2638c29 | 2049 | /* 1 is for ASN_BIT_STRING */ |
toddouska | 0:5045d2638c29 | 2050 | /* algo */ |
toddouska | 0:5045d2638c29 | 2051 | XMEMCPY(output + idx, algo, algoSz); |
toddouska | 0:5045d2638c29 | 2052 | idx += algoSz; |
toddouska | 0:5045d2638c29 | 2053 | /* bit string */ |
toddouska | 0:5045d2638c29 | 2054 | output[idx++] = ASN_BIT_STRING; |
toddouska | 0:5045d2638c29 | 2055 | /* length */ |
toddouska | 0:5045d2638c29 | 2056 | XMEMCPY(output + idx, len, lenSz); |
toddouska | 0:5045d2638c29 | 2057 | idx += lenSz; |
toddouska | 0:5045d2638c29 | 2058 | /* seq */ |
toddouska | 0:5045d2638c29 | 2059 | XMEMCPY(output + idx, seq, seqSz); |
toddouska | 0:5045d2638c29 | 2060 | idx += seqSz; |
toddouska | 0:5045d2638c29 | 2061 | /* n */ |
toddouska | 0:5045d2638c29 | 2062 | XMEMCPY(output + idx, n, nSz); |
toddouska | 0:5045d2638c29 | 2063 | idx += nSz; |
toddouska | 0:5045d2638c29 | 2064 | /* e */ |
toddouska | 0:5045d2638c29 | 2065 | XMEMCPY(output + idx, e, eSz); |
toddouska | 0:5045d2638c29 | 2066 | idx += eSz; |
toddouska | 0:5045d2638c29 | 2067 | |
toddouska | 0:5045d2638c29 | 2068 | return idx; |
toddouska | 0:5045d2638c29 | 2069 | } |
toddouska | 0:5045d2638c29 | 2070 | |
toddouska | 0:5045d2638c29 | 2071 | |
toddouska | 0:5045d2638c29 | 2072 | static INLINE byte itob(int number) |
toddouska | 0:5045d2638c29 | 2073 | { |
toddouska | 0:5045d2638c29 | 2074 | return (byte)number + 0x30; |
toddouska | 0:5045d2638c29 | 2075 | } |
toddouska | 0:5045d2638c29 | 2076 | |
toddouska | 0:5045d2638c29 | 2077 | |
toddouska | 0:5045d2638c29 | 2078 | /* write time to output, format */ |
toddouska | 0:5045d2638c29 | 2079 | static void SetTime(struct tm* date, byte* output) |
toddouska | 0:5045d2638c29 | 2080 | { |
toddouska | 0:5045d2638c29 | 2081 | int i = 0; |
toddouska | 0:5045d2638c29 | 2082 | |
toddouska | 0:5045d2638c29 | 2083 | output[i++] = itob((date->tm_year % 10000) / 1000); |
toddouska | 0:5045d2638c29 | 2084 | output[i++] = itob((date->tm_year % 1000) / 100); |
toddouska | 0:5045d2638c29 | 2085 | output[i++] = itob((date->tm_year % 100) / 10); |
toddouska | 0:5045d2638c29 | 2086 | output[i++] = itob( date->tm_year % 10); |
toddouska | 0:5045d2638c29 | 2087 | |
toddouska | 0:5045d2638c29 | 2088 | output[i++] = itob(date->tm_mon / 10); |
toddouska | 0:5045d2638c29 | 2089 | output[i++] = itob(date->tm_mon % 10); |
toddouska | 0:5045d2638c29 | 2090 | |
toddouska | 0:5045d2638c29 | 2091 | output[i++] = itob(date->tm_mday / 10); |
toddouska | 0:5045d2638c29 | 2092 | output[i++] = itob(date->tm_mday % 10); |
toddouska | 0:5045d2638c29 | 2093 | |
toddouska | 0:5045d2638c29 | 2094 | output[i++] = itob(date->tm_hour / 10); |
toddouska | 0:5045d2638c29 | 2095 | output[i++] = itob(date->tm_hour % 10); |
toddouska | 0:5045d2638c29 | 2096 | |
toddouska | 0:5045d2638c29 | 2097 | output[i++] = itob(date->tm_min / 10); |
toddouska | 0:5045d2638c29 | 2098 | output[i++] = itob(date->tm_min % 10); |
toddouska | 0:5045d2638c29 | 2099 | |
toddouska | 0:5045d2638c29 | 2100 | output[i++] = itob(date->tm_sec / 10); |
toddouska | 0:5045d2638c29 | 2101 | output[i++] = itob(date->tm_sec % 10); |
toddouska | 0:5045d2638c29 | 2102 | |
toddouska | 0:5045d2638c29 | 2103 | output[i] = 'Z'; /* Zulu profiel */ |
toddouska | 0:5045d2638c29 | 2104 | } |
toddouska | 0:5045d2638c29 | 2105 | |
toddouska | 0:5045d2638c29 | 2106 | |
toddouska | 0:5045d2638c29 | 2107 | /* Set Date validity from now until now + daysValid */ |
toddouska | 0:5045d2638c29 | 2108 | static int SetValidity(byte* output, int daysValid) |
toddouska | 0:5045d2638c29 | 2109 | { |
toddouska | 0:5045d2638c29 | 2110 | byte before[MAX_DATE_SIZE]; |
toddouska | 0:5045d2638c29 | 2111 | byte after[MAX_DATE_SIZE]; |
toddouska | 0:5045d2638c29 | 2112 | |
toddouska | 0:5045d2638c29 | 2113 | int beforeSz; |
toddouska | 0:5045d2638c29 | 2114 | int afterSz; |
toddouska | 0:5045d2638c29 | 2115 | int seqSz; |
toddouska | 0:5045d2638c29 | 2116 | |
toddouska | 0:5045d2638c29 | 2117 | time_t ticks; |
toddouska | 0:5045d2638c29 | 2118 | struct tm* now; |
toddouska | 0:5045d2638c29 | 2119 | struct tm local; |
toddouska | 0:5045d2638c29 | 2120 | |
toddouska | 0:5045d2638c29 | 2121 | ticks = XTIME(0); |
toddouska | 0:5045d2638c29 | 2122 | now = XGMTIME(&ticks); |
toddouska | 0:5045d2638c29 | 2123 | |
toddouska | 0:5045d2638c29 | 2124 | /* before now */ |
toddouska | 0:5045d2638c29 | 2125 | local = *now; |
toddouska | 0:5045d2638c29 | 2126 | before[0] = ASN_GENERALIZED_TIME; |
toddouska | 0:5045d2638c29 | 2127 | beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */ |
toddouska | 0:5045d2638c29 | 2128 | |
toddouska | 0:5045d2638c29 | 2129 | /* adjust */ |
toddouska | 0:5045d2638c29 | 2130 | local.tm_year += 1900; |
toddouska | 0:5045d2638c29 | 2131 | local.tm_mon += 1; |
toddouska | 0:5045d2638c29 | 2132 | |
toddouska | 0:5045d2638c29 | 2133 | SetTime(&local, before + beforeSz); |
toddouska | 0:5045d2638c29 | 2134 | beforeSz += ASN_GEN_TIME_SZ; |
toddouska | 0:5045d2638c29 | 2135 | |
toddouska | 0:5045d2638c29 | 2136 | /* after now + daysValid */ |
toddouska | 0:5045d2638c29 | 2137 | local = *now; |
toddouska | 0:5045d2638c29 | 2138 | after[0] = ASN_GENERALIZED_TIME; |
toddouska | 0:5045d2638c29 | 2139 | afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */ |
toddouska | 0:5045d2638c29 | 2140 | |
toddouska | 0:5045d2638c29 | 2141 | /* add daysValid */ |
toddouska | 0:5045d2638c29 | 2142 | local.tm_mday += daysValid; |
toddouska | 0:5045d2638c29 | 2143 | mktime(&local); |
toddouska | 0:5045d2638c29 | 2144 | |
toddouska | 0:5045d2638c29 | 2145 | /* adjust */ |
toddouska | 0:5045d2638c29 | 2146 | local.tm_year += 1900; |
toddouska | 0:5045d2638c29 | 2147 | local.tm_mon += 1; |
toddouska | 0:5045d2638c29 | 2148 | |
toddouska | 0:5045d2638c29 | 2149 | SetTime(&local, after + afterSz); |
toddouska | 0:5045d2638c29 | 2150 | afterSz += ASN_GEN_TIME_SZ; |
toddouska | 0:5045d2638c29 | 2151 | |
toddouska | 0:5045d2638c29 | 2152 | /* headers and output */ |
toddouska | 0:5045d2638c29 | 2153 | seqSz = SetSequence(beforeSz + afterSz, output); |
toddouska | 0:5045d2638c29 | 2154 | XMEMCPY(output + seqSz, before, beforeSz); |
toddouska | 0:5045d2638c29 | 2155 | XMEMCPY(output + seqSz + beforeSz, after, afterSz); |
toddouska | 0:5045d2638c29 | 2156 | |
toddouska | 0:5045d2638c29 | 2157 | return seqSz + beforeSz + afterSz; |
toddouska | 0:5045d2638c29 | 2158 | } |
toddouska | 0:5045d2638c29 | 2159 | |
toddouska | 0:5045d2638c29 | 2160 | |
toddouska | 0:5045d2638c29 | 2161 | /* ASN Encoded Name field */ |
toddouska | 0:5045d2638c29 | 2162 | typedef struct EncodedName { |
toddouska | 0:5045d2638c29 | 2163 | int nameLen; /* actual string value length */ |
toddouska | 0:5045d2638c29 | 2164 | int totalLen; /* total encodeding length */ |
toddouska | 0:5045d2638c29 | 2165 | int type; /* type of name */ |
toddouska | 0:5045d2638c29 | 2166 | int used; /* are we actually using this one */ |
toddouska | 0:5045d2638c29 | 2167 | byte encoded[NAME_SIZE * 2]; /* encoding */ |
toddouska | 0:5045d2638c29 | 2168 | } EncodedName; |
toddouska | 0:5045d2638c29 | 2169 | |
toddouska | 0:5045d2638c29 | 2170 | |
toddouska | 0:5045d2638c29 | 2171 | /* Get Which Name from index */ |
toddouska | 0:5045d2638c29 | 2172 | static const char* GetOneName(CertName* name, int index) |
toddouska | 0:5045d2638c29 | 2173 | { |
toddouska | 0:5045d2638c29 | 2174 | switch (index) { |
toddouska | 0:5045d2638c29 | 2175 | case 0: |
toddouska | 0:5045d2638c29 | 2176 | return name->country; |
toddouska | 0:5045d2638c29 | 2177 | break; |
toddouska | 0:5045d2638c29 | 2178 | case 1: |
toddouska | 0:5045d2638c29 | 2179 | return name->state; |
toddouska | 0:5045d2638c29 | 2180 | break; |
toddouska | 0:5045d2638c29 | 2181 | case 2: |
toddouska | 0:5045d2638c29 | 2182 | return name->locality; |
toddouska | 0:5045d2638c29 | 2183 | break; |
toddouska | 0:5045d2638c29 | 2184 | case 3: |
toddouska | 0:5045d2638c29 | 2185 | return name->sur; |
toddouska | 0:5045d2638c29 | 2186 | break; |
toddouska | 0:5045d2638c29 | 2187 | case 4: |
toddouska | 0:5045d2638c29 | 2188 | return name->org; |
toddouska | 0:5045d2638c29 | 2189 | break; |
toddouska | 0:5045d2638c29 | 2190 | case 5: |
toddouska | 0:5045d2638c29 | 2191 | return name->unit; |
toddouska | 0:5045d2638c29 | 2192 | break; |
toddouska | 0:5045d2638c29 | 2193 | case 6: |
toddouska | 0:5045d2638c29 | 2194 | return name->commonName; |
toddouska | 0:5045d2638c29 | 2195 | break; |
toddouska | 0:5045d2638c29 | 2196 | case 7: |
toddouska | 0:5045d2638c29 | 2197 | return name->email; |
toddouska | 0:5045d2638c29 | 2198 | break; |
toddouska | 0:5045d2638c29 | 2199 | default: |
toddouska | 0:5045d2638c29 | 2200 | return 0; |
toddouska | 0:5045d2638c29 | 2201 | } |
toddouska | 0:5045d2638c29 | 2202 | |
toddouska | 0:5045d2638c29 | 2203 | return 0; |
toddouska | 0:5045d2638c29 | 2204 | } |
toddouska | 0:5045d2638c29 | 2205 | |
toddouska | 0:5045d2638c29 | 2206 | |
toddouska | 0:5045d2638c29 | 2207 | /* Get ASN Name from index */ |
toddouska | 0:5045d2638c29 | 2208 | static byte GetNameId(int index) |
toddouska | 0:5045d2638c29 | 2209 | { |
toddouska | 0:5045d2638c29 | 2210 | switch (index) { |
toddouska | 0:5045d2638c29 | 2211 | case 0: |
toddouska | 0:5045d2638c29 | 2212 | return ASN_COUNTRY_NAME; |
toddouska | 0:5045d2638c29 | 2213 | break; |
toddouska | 0:5045d2638c29 | 2214 | case 1: |
toddouska | 0:5045d2638c29 | 2215 | return ASN_STATE_NAME; |
toddouska | 0:5045d2638c29 | 2216 | break; |
toddouska | 0:5045d2638c29 | 2217 | case 2: |
toddouska | 0:5045d2638c29 | 2218 | return ASN_LOCALITY_NAME; |
toddouska | 0:5045d2638c29 | 2219 | break; |
toddouska | 0:5045d2638c29 | 2220 | case 3: |
toddouska | 0:5045d2638c29 | 2221 | return ASN_SUR_NAME; |
toddouska | 0:5045d2638c29 | 2222 | break; |
toddouska | 0:5045d2638c29 | 2223 | case 4: |
toddouska | 0:5045d2638c29 | 2224 | return ASN_ORG_NAME; |
toddouska | 0:5045d2638c29 | 2225 | break; |
toddouska | 0:5045d2638c29 | 2226 | case 5: |
toddouska | 0:5045d2638c29 | 2227 | return ASN_ORGUNIT_NAME; |
toddouska | 0:5045d2638c29 | 2228 | break; |
toddouska | 0:5045d2638c29 | 2229 | case 6: |
toddouska | 0:5045d2638c29 | 2230 | return ASN_COMMON_NAME; |
toddouska | 0:5045d2638c29 | 2231 | break; |
toddouska | 0:5045d2638c29 | 2232 | case 7: |
toddouska | 0:5045d2638c29 | 2233 | /* email uses different id type */ |
toddouska | 0:5045d2638c29 | 2234 | return 0; |
toddouska | 0:5045d2638c29 | 2235 | break; |
toddouska | 0:5045d2638c29 | 2236 | default: |
toddouska | 0:5045d2638c29 | 2237 | return 0; |
toddouska | 0:5045d2638c29 | 2238 | } |
toddouska | 0:5045d2638c29 | 2239 | |
toddouska | 0:5045d2638c29 | 2240 | return 0; |
toddouska | 0:5045d2638c29 | 2241 | } |
toddouska | 0:5045d2638c29 | 2242 | |
toddouska | 0:5045d2638c29 | 2243 | |
toddouska | 0:5045d2638c29 | 2244 | /* encode CertName into output, return total bytes written */ |
toddouska | 0:5045d2638c29 | 2245 | static int SetName(byte* output, CertName* name) |
toddouska | 0:5045d2638c29 | 2246 | { |
toddouska | 0:5045d2638c29 | 2247 | int totalBytes = 0, i, idx; |
toddouska | 0:5045d2638c29 | 2248 | EncodedName names[NAME_ENTRIES]; |
toddouska | 0:5045d2638c29 | 2249 | |
toddouska | 0:5045d2638c29 | 2250 | for (i = 0; i < NAME_ENTRIES; i++) { |
toddouska | 0:5045d2638c29 | 2251 | const char* nameStr = GetOneName(name, i); |
toddouska | 0:5045d2638c29 | 2252 | if (nameStr) { |
toddouska | 0:5045d2638c29 | 2253 | /* bottom up */ |
toddouska | 0:5045d2638c29 | 2254 | byte firstLen[MAX_LENGTH_SZ]; |
toddouska | 0:5045d2638c29 | 2255 | byte secondLen[MAX_LENGTH_SZ]; |
toddouska | 0:5045d2638c29 | 2256 | byte sequence[MAX_SEQ_SZ]; |
toddouska | 0:5045d2638c29 | 2257 | byte set[MAX_SET_SZ]; |
toddouska | 0:5045d2638c29 | 2258 | |
toddouska | 0:5045d2638c29 | 2259 | int email = i == (NAME_ENTRIES - 1) ? 1 : 0; |
toddouska | 0:5045d2638c29 | 2260 | int strLen = XSTRLEN(nameStr); |
toddouska | 0:5045d2638c29 | 2261 | int thisLen = strLen; |
toddouska | 0:5045d2638c29 | 2262 | int firstSz, secondSz, seqSz, setSz; |
toddouska | 0:5045d2638c29 | 2263 | |
toddouska | 0:5045d2638c29 | 2264 | if (strLen == 0) { /* no user data for this item */ |
toddouska | 0:5045d2638c29 | 2265 | names[i].used = 0; |
toddouska | 0:5045d2638c29 | 2266 | continue; |
toddouska | 0:5045d2638c29 | 2267 | } |
toddouska | 0:5045d2638c29 | 2268 | |
toddouska | 0:5045d2638c29 | 2269 | secondSz = SetLength(strLen, secondLen); |
toddouska | 0:5045d2638c29 | 2270 | thisLen += secondSz; |
toddouska | 0:5045d2638c29 | 2271 | if (email) { |
toddouska | 0:5045d2638c29 | 2272 | thisLen += EMAIL_JOINT_LEN; |
toddouska | 0:5045d2638c29 | 2273 | thisLen ++; /* id type */ |
toddouska | 0:5045d2638c29 | 2274 | firstSz = SetLength(EMAIL_JOINT_LEN, firstLen); |
toddouska | 0:5045d2638c29 | 2275 | } |
toddouska | 0:5045d2638c29 | 2276 | else { |
toddouska | 0:5045d2638c29 | 2277 | thisLen++; /* str type */ |
toddouska | 0:5045d2638c29 | 2278 | thisLen++; /* id type */ |
toddouska | 0:5045d2638c29 | 2279 | thisLen += JOINT_LEN; |
toddouska | 0:5045d2638c29 | 2280 | firstSz = SetLength(JOINT_LEN + 1, firstLen); |
toddouska | 0:5045d2638c29 | 2281 | } |
toddouska | 0:5045d2638c29 | 2282 | thisLen += firstSz; |
toddouska | 0:5045d2638c29 | 2283 | thisLen++; /* object id */ |
toddouska | 0:5045d2638c29 | 2284 | |
toddouska | 0:5045d2638c29 | 2285 | seqSz = SetSequence(thisLen, sequence); |
toddouska | 0:5045d2638c29 | 2286 | thisLen += seqSz; |
toddouska | 0:5045d2638c29 | 2287 | setSz = SetSet(thisLen, set); |
toddouska | 0:5045d2638c29 | 2288 | thisLen += setSz; |
toddouska | 0:5045d2638c29 | 2289 | |
toddouska | 0:5045d2638c29 | 2290 | if (thisLen > sizeof(names[i].encoded)) |
toddouska | 0:5045d2638c29 | 2291 | return BUFFER_E; |
toddouska | 0:5045d2638c29 | 2292 | |
toddouska | 0:5045d2638c29 | 2293 | /* store it */ |
toddouska | 0:5045d2638c29 | 2294 | idx = 0; |
toddouska | 0:5045d2638c29 | 2295 | /* set */ |
toddouska | 0:5045d2638c29 | 2296 | XMEMCPY(names[i].encoded, set, setSz); |
toddouska | 0:5045d2638c29 | 2297 | idx += setSz; |
toddouska | 0:5045d2638c29 | 2298 | /* seq */ |
toddouska | 0:5045d2638c29 | 2299 | XMEMCPY(names[i].encoded + idx, sequence, seqSz); |
toddouska | 0:5045d2638c29 | 2300 | idx += seqSz; |
toddouska | 0:5045d2638c29 | 2301 | /* asn object id */ |
toddouska | 0:5045d2638c29 | 2302 | names[i].encoded[idx++] = ASN_OBJECT_ID; |
toddouska | 0:5045d2638c29 | 2303 | /* first length */ |
toddouska | 0:5045d2638c29 | 2304 | XMEMCPY(names[i].encoded + idx, firstLen, firstSz); |
toddouska | 0:5045d2638c29 | 2305 | idx += firstSz; |
toddouska | 0:5045d2638c29 | 2306 | if (email) { |
toddouska | 0:5045d2638c29 | 2307 | const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, |
toddouska | 0:5045d2638c29 | 2308 | 0x01, 0x09, 0x01, 0x16 }; |
toddouska | 0:5045d2638c29 | 2309 | /* email joint id */ |
toddouska | 0:5045d2638c29 | 2310 | XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); |
toddouska | 0:5045d2638c29 | 2311 | idx += sizeof(EMAIL_OID); |
toddouska | 0:5045d2638c29 | 2312 | } |
toddouska | 0:5045d2638c29 | 2313 | else { |
toddouska | 0:5045d2638c29 | 2314 | /* joint id */ |
toddouska | 0:5045d2638c29 | 2315 | names[i].encoded[idx++] = 0x55; |
toddouska | 0:5045d2638c29 | 2316 | names[i].encoded[idx++] = 0x04; |
toddouska | 0:5045d2638c29 | 2317 | /* id type */ |
toddouska | 0:5045d2638c29 | 2318 | names[i].encoded[idx++] = GetNameId(i); |
toddouska | 0:5045d2638c29 | 2319 | /* str type */ |
toddouska | 0:5045d2638c29 | 2320 | names[i].encoded[idx++] = 0x13; |
toddouska | 0:5045d2638c29 | 2321 | } |
toddouska | 0:5045d2638c29 | 2322 | /* second length */ |
toddouska | 0:5045d2638c29 | 2323 | XMEMCPY(names[i].encoded + idx, secondLen, secondSz); |
toddouska | 0:5045d2638c29 | 2324 | idx += secondSz; |
toddouska | 0:5045d2638c29 | 2325 | /* str value */ |
toddouska | 0:5045d2638c29 | 2326 | XMEMCPY(names[i].encoded + idx, nameStr, strLen); |
toddouska | 0:5045d2638c29 | 2327 | idx += strLen; |
toddouska | 0:5045d2638c29 | 2328 | |
toddouska | 0:5045d2638c29 | 2329 | totalBytes += idx; |
toddouska | 0:5045d2638c29 | 2330 | names[i].totalLen = idx; |
toddouska | 0:5045d2638c29 | 2331 | names[i].used = 1; |
toddouska | 0:5045d2638c29 | 2332 | } |
toddouska | 0:5045d2638c29 | 2333 | else |
toddouska | 0:5045d2638c29 | 2334 | names[i].used = 0; |
toddouska | 0:5045d2638c29 | 2335 | } |
toddouska | 0:5045d2638c29 | 2336 | |
toddouska | 0:5045d2638c29 | 2337 | /* header */ |
toddouska | 0:5045d2638c29 | 2338 | idx = SetSequence(totalBytes, output); |
toddouska | 0:5045d2638c29 | 2339 | totalBytes += idx; |
toddouska | 0:5045d2638c29 | 2340 | if (totalBytes > ASN_NAME_MAX) |
toddouska | 0:5045d2638c29 | 2341 | return BUFFER_E; |
toddouska | 0:5045d2638c29 | 2342 | |
toddouska | 0:5045d2638c29 | 2343 | for (i = 0; i < NAME_ENTRIES; i++) { |
toddouska | 0:5045d2638c29 | 2344 | if (names[i].used) { |
toddouska | 0:5045d2638c29 | 2345 | XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); |
toddouska | 0:5045d2638c29 | 2346 | idx += names[i].totalLen; |
toddouska | 0:5045d2638c29 | 2347 | } |
toddouska | 0:5045d2638c29 | 2348 | } |
toddouska | 0:5045d2638c29 | 2349 | return totalBytes; |
toddouska | 0:5045d2638c29 | 2350 | } |
toddouska | 0:5045d2638c29 | 2351 | |
toddouska | 0:5045d2638c29 | 2352 | |
toddouska | 0:5045d2638c29 | 2353 | /* encode info from cert into DER enocder format */ |
toddouska | 0:5045d2638c29 | 2354 | static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, RNG* rng, |
toddouska | 0:5045d2638c29 | 2355 | const byte* ntruKey, word16 ntruSz) |
toddouska | 0:5045d2638c29 | 2356 | { |
toddouska | 0:5045d2638c29 | 2357 | /* version */ |
toddouska | 0:5045d2638c29 | 2358 | der->versionSz = SetMyVersion(cert->version, der->version, TRUE); |
toddouska | 0:5045d2638c29 | 2359 | |
toddouska | 0:5045d2638c29 | 2360 | /* serial number */ |
toddouska | 0:5045d2638c29 | 2361 | RNG_GenerateBlock(rng, cert->serial, SERIAL_SIZE); |
toddouska | 0:5045d2638c29 | 2362 | cert->serial[0] = 0x01; /* ensure positive */ |
toddouska | 0:5045d2638c29 | 2363 | der->serialSz = SetSerial(cert->serial, der->serial); |
toddouska | 0:5045d2638c29 | 2364 | |
toddouska | 0:5045d2638c29 | 2365 | /* signature algo */ |
toddouska | 0:5045d2638c29 | 2366 | der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType); |
toddouska | 0:5045d2638c29 | 2367 | if (der->sigAlgoSz == 0) |
toddouska | 0:5045d2638c29 | 2368 | return ALGO_ID_E; |
toddouska | 0:5045d2638c29 | 2369 | |
toddouska | 0:5045d2638c29 | 2370 | /* public key */ |
toddouska | 0:5045d2638c29 | 2371 | if (cert->keyType == RSA_KEY) { |
toddouska | 0:5045d2638c29 | 2372 | der->publicKeySz = SetPublicKey(der->publicKey, rsaKey); |
toddouska | 0:5045d2638c29 | 2373 | if (der->publicKeySz == 0) |
toddouska | 0:5045d2638c29 | 2374 | return PUBLIC_KEY_E; |
toddouska | 0:5045d2638c29 | 2375 | } |
toddouska | 0:5045d2638c29 | 2376 | else { |
toddouska | 0:5045d2638c29 | 2377 | #ifdef HAVE_NTRU |
toddouska | 0:5045d2638c29 | 2378 | word32 rc; |
toddouska | 0:5045d2638c29 | 2379 | word16 encodedSz; |
toddouska | 0:5045d2638c29 | 2380 | |
toddouska | 0:5045d2638c29 | 2381 | rc = crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz, |
toddouska | 0:5045d2638c29 | 2382 | ntruKey, &encodedSz, NULL); |
toddouska | 0:5045d2638c29 | 2383 | if (rc != NTRU_OK) |
toddouska | 0:5045d2638c29 | 2384 | return PUBLIC_KEY_E; |
toddouska | 0:5045d2638c29 | 2385 | if (encodedSz > MAX_PUBLIC_KEY_SZ) |
toddouska | 0:5045d2638c29 | 2386 | return PUBLIC_KEY_E; |
toddouska | 0:5045d2638c29 | 2387 | |
toddouska | 0:5045d2638c29 | 2388 | rc = crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz, |
toddouska | 0:5045d2638c29 | 2389 | ntruKey, &encodedSz, der->publicKey); |
toddouska | 0:5045d2638c29 | 2390 | if (rc != NTRU_OK) |
toddouska | 0:5045d2638c29 | 2391 | return PUBLIC_KEY_E; |
toddouska | 0:5045d2638c29 | 2392 | |
toddouska | 0:5045d2638c29 | 2393 | der->publicKeySz = encodedSz; |
toddouska | 0:5045d2638c29 | 2394 | #endif |
toddouska | 0:5045d2638c29 | 2395 | } |
toddouska | 0:5045d2638c29 | 2396 | |
toddouska | 0:5045d2638c29 | 2397 | /* date validity */ |
toddouska | 0:5045d2638c29 | 2398 | der->validitySz = SetValidity(der->validity, cert->daysValid); |
toddouska | 0:5045d2638c29 | 2399 | if (der->validitySz == 0) |
toddouska | 0:5045d2638c29 | 2400 | return DATE_E; |
toddouska | 0:5045d2638c29 | 2401 | |
toddouska | 0:5045d2638c29 | 2402 | /* subject name */ |
toddouska | 0:5045d2638c29 | 2403 | der->subjectSz = SetName(der->subject, &cert->subject); |
toddouska | 0:5045d2638c29 | 2404 | if (der->subjectSz == 0) |
toddouska | 0:5045d2638c29 | 2405 | return SUBJECT_E; |
toddouska | 0:5045d2638c29 | 2406 | |
toddouska | 0:5045d2638c29 | 2407 | /* issuer name */ |
toddouska | 0:5045d2638c29 | 2408 | der->issuerSz = SetName(der->issuer, cert->selfSigned ? |
toddouska | 0:5045d2638c29 | 2409 | &cert->subject : &cert->issuer); |
toddouska | 0:5045d2638c29 | 2410 | if (der->issuerSz == 0) |
toddouska | 0:5045d2638c29 | 2411 | return ISSUER_E; |
toddouska | 0:5045d2638c29 | 2412 | |
toddouska | 0:5045d2638c29 | 2413 | der->total = der->versionSz + der->serialSz + der->sigAlgoSz + |
toddouska | 0:5045d2638c29 | 2414 | der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz; |
toddouska | 0:5045d2638c29 | 2415 | |
toddouska | 0:5045d2638c29 | 2416 | return 0; |
toddouska | 0:5045d2638c29 | 2417 | } |
toddouska | 0:5045d2638c29 | 2418 | |
toddouska | 0:5045d2638c29 | 2419 | |
toddouska | 0:5045d2638c29 | 2420 | /* write DER encoded cert to buffer, size already checked */ |
toddouska | 0:5045d2638c29 | 2421 | static int WriteCertBody(DerCert* der, byte* buffer) |
toddouska | 0:5045d2638c29 | 2422 | { |
toddouska | 0:5045d2638c29 | 2423 | int idx; |
toddouska | 0:5045d2638c29 | 2424 | |
toddouska | 0:5045d2638c29 | 2425 | /* signed part header */ |
toddouska | 0:5045d2638c29 | 2426 | idx = SetSequence(der->total, buffer); |
toddouska | 0:5045d2638c29 | 2427 | /* version */ |
toddouska | 0:5045d2638c29 | 2428 | XMEMCPY(buffer + idx, der->version, der->versionSz); |
toddouska | 0:5045d2638c29 | 2429 | idx += der->versionSz; |
toddouska | 0:5045d2638c29 | 2430 | /* serial */ |
toddouska | 0:5045d2638c29 | 2431 | XMEMCPY(buffer + idx, der->serial, der->serialSz); |
toddouska | 0:5045d2638c29 | 2432 | idx += der->serialSz; |
toddouska | 0:5045d2638c29 | 2433 | /* sig algo */ |
toddouska | 0:5045d2638c29 | 2434 | XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz); |
toddouska | 0:5045d2638c29 | 2435 | idx += der->sigAlgoSz; |
toddouska | 0:5045d2638c29 | 2436 | /* issuer */ |
toddouska | 0:5045d2638c29 | 2437 | XMEMCPY(buffer + idx, der->issuer, der->issuerSz); |
toddouska | 0:5045d2638c29 | 2438 | idx += der->issuerSz; |
toddouska | 0:5045d2638c29 | 2439 | /* validity */ |
toddouska | 0:5045d2638c29 | 2440 | XMEMCPY(buffer + idx, der->validity, der->validitySz); |
toddouska | 0:5045d2638c29 | 2441 | idx += der->validitySz; |
toddouska | 0:5045d2638c29 | 2442 | /* subject */ |
toddouska | 0:5045d2638c29 | 2443 | XMEMCPY(buffer + idx, der->subject, der->subjectSz); |
toddouska | 0:5045d2638c29 | 2444 | idx += der->subjectSz; |
toddouska | 0:5045d2638c29 | 2445 | /* public key */ |
toddouska | 0:5045d2638c29 | 2446 | XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz); |
toddouska | 0:5045d2638c29 | 2447 | idx += der->publicKeySz; |
toddouska | 0:5045d2638c29 | 2448 | |
toddouska | 0:5045d2638c29 | 2449 | return idx; |
toddouska | 0:5045d2638c29 | 2450 | } |
toddouska | 0:5045d2638c29 | 2451 | |
toddouska | 0:5045d2638c29 | 2452 | |
toddouska | 0:5045d2638c29 | 2453 | /* Make MD5wRSA signature from buffer (sz), write to sig (sigSz) */ |
toddouska | 0:5045d2638c29 | 2454 | static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, |
toddouska | 0:5045d2638c29 | 2455 | RsaKey* key, RNG* rng) |
toddouska | 0:5045d2638c29 | 2456 | { |
toddouska | 0:5045d2638c29 | 2457 | byte digest[SHA_DIGEST_SIZE]; /* max size */ |
toddouska | 0:5045d2638c29 | 2458 | byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ]; |
toddouska | 0:5045d2638c29 | 2459 | int encSigSz, digestSz, hashType; |
toddouska | 0:5045d2638c29 | 2460 | Md5 md5; /* md5 for now */ |
toddouska | 0:5045d2638c29 | 2461 | |
toddouska | 0:5045d2638c29 | 2462 | InitMd5(&md5); |
toddouska | 0:5045d2638c29 | 2463 | Md5Update(&md5, buffer, sz); |
toddouska | 0:5045d2638c29 | 2464 | Md5Final(&md5, digest); |
toddouska | 0:5045d2638c29 | 2465 | digestSz = MD5_DIGEST_SIZE; |
toddouska | 0:5045d2638c29 | 2466 | hashType = MD5h; |
toddouska | 0:5045d2638c29 | 2467 | |
toddouska | 0:5045d2638c29 | 2468 | /* signature */ |
toddouska | 0:5045d2638c29 | 2469 | encSigSz = EncodeSignature(encSig, digest, digestSz, hashType); |
toddouska | 0:5045d2638c29 | 2470 | return RsaSSL_Sign(encSig, encSigSz, sig, sigSz, key, rng); |
toddouska | 0:5045d2638c29 | 2471 | } |
toddouska | 0:5045d2638c29 | 2472 | |
toddouska | 0:5045d2638c29 | 2473 | |
toddouska | 0:5045d2638c29 | 2474 | /* add signature to end of buffer, size of buffer assumed checked, return |
toddouska | 0:5045d2638c29 | 2475 | new length */ |
toddouska | 0:5045d2638c29 | 2476 | static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz) |
toddouska | 0:5045d2638c29 | 2477 | { |
toddouska | 0:5045d2638c29 | 2478 | byte seq[MAX_SEQ_SZ]; |
toddouska | 0:5045d2638c29 | 2479 | int idx = bodySz, seqSz; |
toddouska | 0:5045d2638c29 | 2480 | |
toddouska | 0:5045d2638c29 | 2481 | /* algo */ |
toddouska | 0:5045d2638c29 | 2482 | idx += SetAlgoID(MD5wRSA, buffer + idx, sigType); |
toddouska | 0:5045d2638c29 | 2483 | /* bit string */ |
toddouska | 0:5045d2638c29 | 2484 | buffer[idx++] = ASN_BIT_STRING; |
toddouska | 0:5045d2638c29 | 2485 | /* length */ |
toddouska | 0:5045d2638c29 | 2486 | idx += SetLength(sigSz + 1, buffer + idx); |
toddouska | 0:5045d2638c29 | 2487 | buffer[idx++] = 0; /* trailing 0 */ |
toddouska | 0:5045d2638c29 | 2488 | /* signature */ |
toddouska | 0:5045d2638c29 | 2489 | XMEMCPY(buffer + idx, sig, sigSz); |
toddouska | 0:5045d2638c29 | 2490 | idx += sigSz; |
toddouska | 0:5045d2638c29 | 2491 | |
toddouska | 0:5045d2638c29 | 2492 | /* make room for overall header */ |
toddouska | 0:5045d2638c29 | 2493 | seqSz = SetSequence(idx, seq); |
toddouska | 0:5045d2638c29 | 2494 | XMEMMOVE(buffer + seqSz, buffer, idx); |
toddouska | 0:5045d2638c29 | 2495 | XMEMCPY(buffer, seq, seqSz); |
toddouska | 0:5045d2638c29 | 2496 | |
toddouska | 0:5045d2638c29 | 2497 | return idx + seqSz; |
toddouska | 0:5045d2638c29 | 2498 | } |
toddouska | 0:5045d2638c29 | 2499 | |
toddouska | 0:5045d2638c29 | 2500 | |
toddouska | 0:5045d2638c29 | 2501 | /* Make an x509 Certificate v3 any key type from cert input, write to buffer */ |
toddouska | 0:5045d2638c29 | 2502 | static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, |
toddouska | 0:5045d2638c29 | 2503 | RsaKey* rsaKey, RNG* rng, const byte* ntruKey, word16 ntruSz) |
toddouska | 0:5045d2638c29 | 2504 | { |
toddouska | 0:5045d2638c29 | 2505 | DerCert der; |
toddouska | 0:5045d2638c29 | 2506 | int ret; |
toddouska | 0:5045d2638c29 | 2507 | |
toddouska | 0:5045d2638c29 | 2508 | cert->keyType = rsaKey ? RSA_KEY : NTRU_KEY; |
toddouska | 0:5045d2638c29 | 2509 | ret = EncodeCert(cert, &der, rsaKey, rng, ntruKey, ntruSz); |
toddouska | 0:5045d2638c29 | 2510 | if (ret != 0) |
toddouska | 0:5045d2638c29 | 2511 | return ret; |
toddouska | 0:5045d2638c29 | 2512 | |
toddouska | 0:5045d2638c29 | 2513 | if (der.total + MAX_SEQ_SZ * 2 > (int)derSz) |
toddouska | 0:5045d2638c29 | 2514 | return BUFFER_E; |
toddouska | 0:5045d2638c29 | 2515 | |
toddouska | 0:5045d2638c29 | 2516 | return cert->bodySz = WriteCertBody(&der, derBuffer); |
toddouska | 0:5045d2638c29 | 2517 | } |
toddouska | 0:5045d2638c29 | 2518 | |
toddouska | 0:5045d2638c29 | 2519 | |
toddouska | 0:5045d2638c29 | 2520 | /* Make an x509 Certificate v3 RSA from cert input, write to buffer */ |
toddouska | 0:5045d2638c29 | 2521 | int MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,RNG* rng) |
toddouska | 0:5045d2638c29 | 2522 | { |
toddouska | 0:5045d2638c29 | 2523 | return MakeAnyCert(cert, derBuffer, derSz, rsaKey, rng, NULL, 0); |
toddouska | 0:5045d2638c29 | 2524 | } |
toddouska | 0:5045d2638c29 | 2525 | |
toddouska | 0:5045d2638c29 | 2526 | |
toddouska | 0:5045d2638c29 | 2527 | #ifdef HAVE_NTRU |
toddouska | 0:5045d2638c29 | 2528 | |
toddouska | 0:5045d2638c29 | 2529 | int MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz, |
toddouska | 0:5045d2638c29 | 2530 | const byte* ntruKey, word16 keySz, RNG* rng) |
toddouska | 0:5045d2638c29 | 2531 | { |
toddouska | 0:5045d2638c29 | 2532 | return MakeAnyCert(cert, derBuffer, derSz, NULL, rng, ntruKey, keySz); |
toddouska | 0:5045d2638c29 | 2533 | } |
toddouska | 0:5045d2638c29 | 2534 | |
toddouska | 0:5045d2638c29 | 2535 | #endif /* HAVE_NTRU */ |
toddouska | 0:5045d2638c29 | 2536 | |
toddouska | 0:5045d2638c29 | 2537 | |
toddouska | 0:5045d2638c29 | 2538 | int SignCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng) |
toddouska | 0:5045d2638c29 | 2539 | { |
toddouska | 0:5045d2638c29 | 2540 | byte sig[MAX_ENCODED_SIG_SZ]; |
toddouska | 0:5045d2638c29 | 2541 | int sigSz; |
toddouska | 0:5045d2638c29 | 2542 | int bodySz = cert->bodySz; |
toddouska | 0:5045d2638c29 | 2543 | |
toddouska | 0:5045d2638c29 | 2544 | if (bodySz < 0) |
toddouska | 0:5045d2638c29 | 2545 | return bodySz; |
toddouska | 0:5045d2638c29 | 2546 | |
toddouska | 0:5045d2638c29 | 2547 | sigSz = MakeSignature(buffer, bodySz, sig, sizeof(sig), key, rng); |
toddouska | 0:5045d2638c29 | 2548 | if (sigSz < 0) |
toddouska | 0:5045d2638c29 | 2549 | return sigSz; |
toddouska | 0:5045d2638c29 | 2550 | |
toddouska | 0:5045d2638c29 | 2551 | if (bodySz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) |
toddouska | 0:5045d2638c29 | 2552 | return BUFFER_E; |
toddouska | 0:5045d2638c29 | 2553 | |
toddouska | 0:5045d2638c29 | 2554 | return AddSignature(buffer, bodySz, sig, sigSz); |
toddouska | 0:5045d2638c29 | 2555 | } |
toddouska | 0:5045d2638c29 | 2556 | |
toddouska | 0:5045d2638c29 | 2557 | |
toddouska | 0:5045d2638c29 | 2558 | int MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng) |
toddouska | 0:5045d2638c29 | 2559 | { |
toddouska | 0:5045d2638c29 | 2560 | int ret = MakeCert(cert, buffer, buffSz, key, rng); |
toddouska | 0:5045d2638c29 | 2561 | |
toddouska | 0:5045d2638c29 | 2562 | if (ret < 0) |
toddouska | 0:5045d2638c29 | 2563 | return ret; |
toddouska | 0:5045d2638c29 | 2564 | |
toddouska | 0:5045d2638c29 | 2565 | return SignCert(cert, buffer, buffSz, key, rng); |
toddouska | 0:5045d2638c29 | 2566 | } |
toddouska | 0:5045d2638c29 | 2567 | |
toddouska | 0:5045d2638c29 | 2568 | |
toddouska | 0:5045d2638c29 | 2569 | /* forward from CyaSSL */ |
toddouska | 0:5045d2638c29 | 2570 | int CyaSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz); |
toddouska | 0:5045d2638c29 | 2571 | |
toddouska | 0:5045d2638c29 | 2572 | #ifndef NO_FILESYSTEM |
toddouska | 0:5045d2638c29 | 2573 | |
toddouska | 0:5045d2638c29 | 2574 | int SetIssuer(Cert* cert, const char* issuerCertFile) |
toddouska | 0:5045d2638c29 | 2575 | { |
toddouska | 0:5045d2638c29 | 2576 | DecodedCert decoded; |
toddouska | 0:5045d2638c29 | 2577 | byte der[8192]; |
toddouska | 0:5045d2638c29 | 2578 | int derSz = CyaSSL_PemCertToDer(issuerCertFile, der, sizeof(der)); |
toddouska | 0:5045d2638c29 | 2579 | int ret; |
toddouska | 0:5045d2638c29 | 2580 | int sz; |
toddouska | 0:5045d2638c29 | 2581 | |
toddouska | 0:5045d2638c29 | 2582 | if (derSz < 0) |
toddouska | 0:5045d2638c29 | 2583 | return derSz; |
toddouska | 0:5045d2638c29 | 2584 | |
toddouska | 0:5045d2638c29 | 2585 | cert->selfSigned = 0; |
toddouska | 0:5045d2638c29 | 2586 | |
toddouska | 0:5045d2638c29 | 2587 | InitDecodedCert(&decoded, der, 0); |
toddouska | 0:5045d2638c29 | 2588 | ret = ParseCertRelative(&decoded, derSz, CA_TYPE, NO_VERIFY, 0); |
toddouska | 0:5045d2638c29 | 2589 | |
toddouska | 0:5045d2638c29 | 2590 | if (ret < 0) |
toddouska | 0:5045d2638c29 | 2591 | return ret; |
toddouska | 0:5045d2638c29 | 2592 | |
toddouska | 0:5045d2638c29 | 2593 | if (decoded.subjectCN) { |
toddouska | 0:5045d2638c29 | 2594 | sz = (decoded.subjectCNLen < NAME_SIZE) ? decoded.subjectCNLen : |
toddouska | 0:5045d2638c29 | 2595 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2596 | strncpy(cert->issuer.commonName, decoded.subjectCN, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2597 | cert->issuer.commonName[sz] = 0; |
toddouska | 0:5045d2638c29 | 2598 | } |
toddouska | 0:5045d2638c29 | 2599 | if (decoded.subjectC) { |
toddouska | 0:5045d2638c29 | 2600 | sz = (decoded.subjectCLen < NAME_SIZE) ? decoded.subjectCLen : |
toddouska | 0:5045d2638c29 | 2601 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2602 | strncpy(cert->issuer.country, decoded.subjectC, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2603 | cert->issuer.country[sz] = 0; |
toddouska | 0:5045d2638c29 | 2604 | } |
toddouska | 0:5045d2638c29 | 2605 | if (decoded.subjectST) { |
toddouska | 0:5045d2638c29 | 2606 | sz = (decoded.subjectSTLen < NAME_SIZE) ? decoded.subjectSTLen : |
toddouska | 0:5045d2638c29 | 2607 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2608 | strncpy(cert->issuer.state, decoded.subjectST, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2609 | cert->issuer.state[sz] = 0; |
toddouska | 0:5045d2638c29 | 2610 | } |
toddouska | 0:5045d2638c29 | 2611 | if (decoded.subjectL) { |
toddouska | 0:5045d2638c29 | 2612 | sz = (decoded.subjectLLen < NAME_SIZE) ? decoded.subjectLLen : |
toddouska | 0:5045d2638c29 | 2613 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2614 | strncpy(cert->issuer.locality, decoded.subjectL, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2615 | cert->issuer.locality[sz] = 0; |
toddouska | 0:5045d2638c29 | 2616 | } |
toddouska | 0:5045d2638c29 | 2617 | if (decoded.subjectO) { |
toddouska | 0:5045d2638c29 | 2618 | sz = (decoded.subjectOLen < NAME_SIZE) ? decoded.subjectOLen : |
toddouska | 0:5045d2638c29 | 2619 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2620 | strncpy(cert->issuer.org, decoded.subjectO, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2621 | cert->issuer.org[sz] = 0; |
toddouska | 0:5045d2638c29 | 2622 | } |
toddouska | 0:5045d2638c29 | 2623 | if (decoded.subjectOU) { |
toddouska | 0:5045d2638c29 | 2624 | sz = (decoded.subjectOULen < NAME_SIZE) ? decoded.subjectOULen : |
toddouska | 0:5045d2638c29 | 2625 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2626 | strncpy(cert->issuer.unit, decoded.subjectOU, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2627 | cert->issuer.unit[sz] = 0; |
toddouska | 0:5045d2638c29 | 2628 | } |
toddouska | 0:5045d2638c29 | 2629 | if (decoded.subjectSN) { |
toddouska | 0:5045d2638c29 | 2630 | sz = (decoded.subjectSNLen < NAME_SIZE) ? decoded.subjectSNLen : |
toddouska | 0:5045d2638c29 | 2631 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2632 | strncpy(cert->issuer.sur, decoded.subjectSN, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2633 | cert->issuer.sur[sz] = 0; |
toddouska | 0:5045d2638c29 | 2634 | } |
toddouska | 0:5045d2638c29 | 2635 | if (decoded.subjectEmail) { |
toddouska | 0:5045d2638c29 | 2636 | sz = (decoded.subjectEmailLen < NAME_SIZE) ? decoded.subjectEmailLen : |
toddouska | 0:5045d2638c29 | 2637 | NAME_SIZE - 1; |
toddouska | 0:5045d2638c29 | 2638 | strncpy(cert->issuer.email, decoded.subjectEmail, NAME_SIZE); |
toddouska | 0:5045d2638c29 | 2639 | cert->issuer.email[sz] = 0; |
toddouska | 0:5045d2638c29 | 2640 | } |
toddouska | 0:5045d2638c29 | 2641 | |
toddouska | 0:5045d2638c29 | 2642 | FreeDecodedCert(&decoded); |
toddouska | 0:5045d2638c29 | 2643 | |
toddouska | 0:5045d2638c29 | 2644 | return 0; |
toddouska | 0:5045d2638c29 | 2645 | } |
toddouska | 0:5045d2638c29 | 2646 | |
toddouska | 0:5045d2638c29 | 2647 | #endif /* NO_FILESYSTEM */ |
toddouska | 0:5045d2638c29 | 2648 | #endif /* CYASSL_CERT_GEN */ |