MultiTech / CyaSSL

Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers asn.c Source File

asn.c

00001 /* asn.c
00002  *
00003  * Copyright (C) 2006-2014 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include <cyassl/ctaocrypt/settings.h>
00027 
00028 #ifndef NO_ASN
00029 
00030 #ifdef HAVE_RTP_SYS
00031     #include "os.h"           /* dc_rtc_api needs    */
00032     #include "dc_rtc_api.h"   /* to get current time */
00033 #endif
00034 
00035 #include <cyassl/ctaocrypt/integer.h>
00036 #include <cyassl/ctaocrypt/asn.h>
00037 #include <cyassl/ctaocrypt/coding.h>
00038 #include <cyassl/ctaocrypt/md2.h>
00039 #include <cyassl/ctaocrypt/hmac.h>
00040 #include <cyassl/ctaocrypt/error-crypt.h>
00041 #include <cyassl/ctaocrypt/pwdbased.h>
00042 #include <cyassl/ctaocrypt/des3.h>
00043 #include <cyassl/ctaocrypt/logging.h>
00044 
00045 #include <cyassl/ctaocrypt/random.h>
00046 
00047 
00048 #ifndef NO_RC4
00049     #include <cyassl/ctaocrypt/arc4.h>
00050 #endif
00051 
00052 #ifdef HAVE_NTRU
00053     #include "ntru_crypto.h"
00054 #endif
00055 
00056 #ifdef HAVE_ECC
00057     #include <cyassl/ctaocrypt/ecc.h>
00058 #endif
00059 
00060 #ifdef CYASSL_DEBUG_ENCODING
00061     #ifdef FREESCALE_MQX
00062         #include <fio.h>
00063     #else
00064         #include <stdio.h>
00065     #endif
00066 #endif
00067 
00068 #ifdef _MSC_VER
00069     /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
00070     #pragma warning(disable: 4996)
00071 #endif
00072 
00073 
00074 #ifndef TRUE
00075     #define TRUE  1
00076 #endif
00077 #ifndef FALSE
00078     #define FALSE 0
00079 #endif
00080 
00081 
00082 #ifdef HAVE_RTP_SYS 
00083     /* uses parital <time.h> structures */
00084     #define XTIME(tl)  (0)
00085     #define XGMTIME(c) my_gmtime((c))
00086     #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
00087 #elif defined(MICRIUM)
00088     #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
00089         #define XVALIDATE_DATE(d,f,t) NetSecure_ValidateDateHandler((d),(f),(t))
00090     #else
00091         #define XVALIDATE_DATE(d, f, t) (0)
00092     #endif
00093     #define NO_TIME_H
00094     /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */
00095 #elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
00096     #include <time.h>
00097     #define XTIME(t1) pic32_time((t1))
00098     #define XGMTIME(c) gmtime((c))
00099     #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
00100 #elif defined(FREESCALE_MQX)
00101     #define XTIME(t1)  mqx_time((t1))
00102     #define XGMTIME(c) mqx_gmtime((c))
00103     #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
00104 #elif defined(CYASSL_MDK_ARM)
00105     #if defined(CYASSL_MDK5)
00106         #include "cmsis_os.h"
00107     #else
00108         #include <rtl.h>
00109     #endif
00110     #undef RNG
00111     #include "cyassl_MDK_ARM.h"
00112     #undef RNG
00113     #define RNG CyaSSL_RNG /*for avoiding name conflict in "stm32f2xx.h" */
00114     #define XTIME(tl)  (0)
00115     #define XGMTIME(c) Cyassl_MDK_gmtime((c))
00116     #define XVALIDATE_DATE(d, f, t)  ValidateDate((d), (f), (t))
00117 #elif defined(USER_TIME)
00118     /* user time, and gmtime compatible functions, there is a gmtime 
00119        implementation here that WINCE uses, so really just need some ticks
00120        since the EPOCH 
00121     */
00122 
00123     struct tm {
00124     int tm_sec;     /* seconds after the minute [0-60] */
00125     int tm_min;     /* minutes after the hour [0-59] */
00126     int tm_hour;    /* hours since midnight [0-23] */
00127     int tm_mday;    /* day of the month [1-31] */
00128     int tm_mon;     /* months since January [0-11] */
00129     int tm_year;    /* years since 1900 */
00130     int tm_wday;    /* days since Sunday [0-6] */
00131     int tm_yday;    /* days since January 1 [0-365] */
00132     int tm_isdst;   /* Daylight Savings Time flag */
00133     long    tm_gmtoff;  /* offset from CUT in seconds */
00134     char    *tm_zone;   /* timezone abbreviation */
00135     };
00136     typedef long time_t;
00137 
00138     /* forward declaration */
00139     struct tm* gmtime(const time_t* timer);
00140     time_t XTIME(time_t * timer){
00141         return time(timer);
00142     }
00143 
00144     #define XGMTIME(c) gmtime((c))
00145     #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
00146 
00147     #ifdef STACK_TRAP
00148         /* for stack trap tracking, don't call os gmtime on OS X/linux,
00149            uses a lot of stack spce */
00150         extern time_t time(time_t * timer);
00151         #define XTIME(tl)  time((tl))
00152     #endif /* STACK_TRAP */
00153 
00154 #else
00155     /* default */
00156     /* uses complete <time.h> facility */
00157     #include <time.h>
00158     #define XTIME(tl)  time((tl))
00159     #define XGMTIME(c) gmtime((c))
00160     #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
00161 #endif
00162 
00163 
00164 #ifdef _WIN32_WCE
00165 /* no time() or gmtime() even though in time.h header?? */
00166 
00167 #include <windows.h>
00168 
00169 
00170 time_t time(time_t* timer)
00171 {
00172     SYSTEMTIME     sysTime;
00173     FILETIME       fTime;
00174     ULARGE_INTEGER intTime;
00175     time_t         localTime;
00176 
00177     if (timer == NULL)
00178         timer = &localTime;
00179 
00180     GetSystemTime(&sysTime);
00181     SystemTimeToFileTime(&sysTime, &fTime);
00182     
00183     XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
00184     /* subtract EPOCH */
00185     intTime.QuadPart -= 0x19db1ded53e8000;
00186     /* to secs */
00187     intTime.QuadPart /= 10000000;
00188     *timer = (time_t)intTime.QuadPart;
00189 
00190     return *timer;
00191 }
00192 
00193 #endif /*  _WIN32_WCE */
00194 #if defined( _WIN32_WCE ) || defined( USER_TIME )
00195 
00196 struct tm* gmtime(const time_t* timer)
00197 {
00198     #define YEAR0          1900
00199     #define EPOCH_YEAR     1970
00200     #define SECS_DAY       (24L * 60L * 60L)
00201     #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
00202     #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
00203 
00204     static const int _ytab[2][12] =
00205     {
00206         {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
00207         {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
00208     };
00209 
00210     static struct tm st_time;
00211     struct tm* ret = &st_time;
00212     time_t secs = *timer;
00213     unsigned long dayclock, dayno;
00214     int year = EPOCH_YEAR;
00215 
00216     dayclock = (unsigned long)secs % SECS_DAY;
00217     dayno    = (unsigned long)secs / SECS_DAY;
00218 
00219     ret->tm_sec  = (int) dayclock % 60;
00220     ret->tm_min  = (int)(dayclock % 3600) / 60;
00221     ret->tm_hour = (int) dayclock / 3600;
00222     ret->tm_wday = (int) (dayno + 4) % 7;        /* day 0 a Thursday */
00223 
00224     while(dayno >= (unsigned long)YEARSIZE(year)) {
00225         dayno -= YEARSIZE(year);
00226         year++;
00227     }
00228 
00229     ret->tm_year = year - YEAR0;
00230     ret->tm_yday = (int)dayno;
00231     ret->tm_mon  = 0;
00232 
00233     while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
00234         dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
00235         ret->tm_mon++;
00236     }
00237 
00238     ret->tm_mday  = (int)++dayno;
00239     ret->tm_isdst = 0;
00240 
00241     return ret;
00242 }
00243 
00244 #endif /* _WIN32_WCE  || USER_TIME */
00245 
00246 
00247 #ifdef HAVE_RTP_SYS  
00248 
00249 #define YEAR0          1900
00250 
00251 struct tm* my_gmtime(const time_t* timer)       /* has a gmtime() but hangs */
00252 {
00253     static struct tm st_time;
00254     struct tm* ret = &st_time;
00255 
00256     DC_RTC_CALENDAR cal;
00257     dc_rtc_time_get(&cal, TRUE);
00258 
00259     ret->tm_year  = cal.year - YEAR0;       /* gm starts at 1900 */
00260     ret->tm_mon   = cal.month - 1;          /* gm starts at 0 */
00261     ret->tm_mday  = cal.day;
00262     ret->tm_hour  = cal.hour;
00263     ret->tm_min   = cal.minute;
00264     ret->tm_sec   = cal.second;
00265 
00266     return ret;
00267 }
00268 
00269 #endif /* HAVE_RTP_SYS */
00270 
00271 
00272 #if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
00273 
00274 /*
00275  * time() is just a stub in Microchip libraries. We need our own
00276  * implementation. Use SNTP client to get seconds since epoch.
00277  */
00278 time_t pic32_time(time_t* timer)
00279 {
00280 #ifdef MICROCHIP_TCPIP_V5
00281     DWORD sec = 0;
00282 #else
00283     uint32_t sec = 0;
00284 #endif
00285     time_t localTime;
00286 
00287     if (timer == NULL)
00288         timer = &localTime;
00289 
00290 #ifdef MICROCHIP_MPLAB_HARMONY 
00291     sec = TCPIP_SNTP_UTCSecondsGet();
00292 #else
00293     sec = SNTPGetUTCSeconds();
00294 #endif
00295     *timer = (time_t) sec;
00296 
00297     return *timer;
00298 }
00299 
00300 #endif /* MICROCHIP_TCPIP */
00301 
00302 
00303 #ifdef FREESCALE_MQX
00304 
00305 time_t mqx_time(time_t* timer)
00306 {
00307     time_t localTime;
00308     TIME_STRUCT time_s;
00309 
00310     if (timer == NULL)
00311         timer = &localTime;
00312 
00313     _time_get(&time_s);
00314     *timer = (time_t) time_s.SECONDS;
00315 
00316     return *timer;
00317 }
00318 
00319 /* CodeWarrior GCC toolchain only has gmtime_r(), no gmtime() */
00320 struct tm* mqx_gmtime(const time_t* clock)
00321 {
00322     struct tm tmpTime;
00323 
00324     return gmtime_r(clock, &tmpTime);
00325 }
00326 
00327 #endif /* FREESCALE_MQX */
00328 
00329 #ifdef CYASSL_TIRTOS
00330 
00331 time_t XTIME(time_t * timer)
00332 {
00333     time_t sec = 0;
00334 
00335     sec = (time_t) MYTIME_gettime();
00336 
00337     if (timer != NULL)
00338         *timer = sec;
00339 
00340     return sec;
00341 }
00342 
00343 #endif /* CYASSL_TIRTOS */
00344 
00345 static INLINE word32 btoi(byte b)
00346 {
00347     return b - 0x30;
00348 }
00349 
00350 
00351 /* two byte date/time, add to value */
00352 static INLINE void GetTime(int* value, const byte* date, int* idx)
00353 {
00354     int i = *idx;
00355 
00356     *value += btoi(date[i++]) * 10;
00357     *value += btoi(date[i++]);
00358 
00359     *idx = i;
00360 }
00361 
00362 
00363 #if defined(MICRIUM)
00364 
00365 CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format,
00366                                          CPU_INT08U dateType)
00367 {
00368     CPU_BOOLEAN  rtn_code;
00369     CPU_INT32S   i;
00370     CPU_INT32S   val;    
00371     CPU_INT16U   year;
00372     CPU_INT08U   month;
00373     CPU_INT16U   day;
00374     CPU_INT08U   hour;
00375     CPU_INT08U   min;
00376     CPU_INT08U   sec;
00377 
00378     i    = 0;
00379     year = 0u;
00380 
00381     if (format == ASN_UTC_TIME) {
00382         if (btoi(date[0]) >= 5)
00383             year = 1900;
00384         else
00385             year = 2000;
00386     }
00387     else  { /* format == GENERALIZED_TIME */
00388         year += btoi(date[i++]) * 1000;
00389         year += btoi(date[i++]) * 100;
00390     }    
00391 
00392     val = year;
00393     GetTime(&val, date, &i);
00394     year = (CPU_INT16U)val;
00395 
00396     val = 0;
00397     GetTime(&val, date, &i);   
00398     month = (CPU_INT08U)val;   
00399 
00400     val = 0;
00401     GetTime(&val, date, &i);  
00402     day = (CPU_INT16U)val;
00403 
00404     val = 0;
00405     GetTime(&val, date, &i);  
00406     hour = (CPU_INT08U)val;
00407 
00408     val = 0;
00409     GetTime(&val, date, &i);  
00410     min = (CPU_INT08U)val;
00411 
00412     val = 0;
00413     GetTime(&val, date, &i);  
00414     sec = (CPU_INT08U)val;
00415 
00416     return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType); 
00417 }
00418 
00419 #endif /* MICRIUM */
00420 
00421 
00422 CYASSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
00423                            word32 maxIdx)
00424 {
00425     int     length = 0;
00426     word32  i = *inOutIdx;
00427     byte    b;
00428 
00429     *len = 0;    /* default length */
00430 
00431     if ( (i+1) > maxIdx) {   /* for first read */
00432         CYASSL_MSG("GetLength bad index on input");
00433         return BUFFER_E;
00434     }
00435 
00436     b = input[i++];
00437     if (b >= ASN_LONG_LENGTH) {        
00438         word32 bytes = b & 0x7F;
00439 
00440         if ( (i+bytes) > maxIdx) {   /* for reading bytes */
00441             CYASSL_MSG("GetLength bad long length");
00442             return BUFFER_E;
00443         }
00444 
00445         while (bytes--) {
00446             b = input[i++];
00447             length = (length << 8) | b;
00448         }
00449     }
00450     else
00451         length = b;
00452     
00453     if ( (i+length) > maxIdx) {   /* for user of length */
00454         CYASSL_MSG("GetLength value exceeds buffer length");
00455         return BUFFER_E;
00456     }
00457 
00458     *inOutIdx = i;
00459     if (length > 0)
00460         *len = length;
00461 
00462     return length;
00463 }
00464 
00465 
00466 CYASSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
00467                            word32 maxIdx)
00468 {
00469     int    length = -1;
00470     word32 idx    = *inOutIdx;
00471 
00472     if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
00473             GetLength(input, &idx, &length, maxIdx) < 0)
00474         return ASN_PARSE_E;
00475 
00476     *len      = length;
00477     *inOutIdx = idx;
00478 
00479     return length;
00480 }
00481 
00482 
00483 CYASSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
00484                         word32 maxIdx)
00485 {
00486     int    length = -1;
00487     word32 idx    = *inOutIdx;
00488 
00489     if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) ||
00490             GetLength(input, &idx, &length, maxIdx) < 0)
00491         return ASN_PARSE_E;
00492 
00493     *len      = length;
00494     *inOutIdx = idx;
00495 
00496     return length;
00497 }
00498 
00499 
00500 /* windows header clash for WinCE using GetVersion */
00501 CYASSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version)
00502 {
00503     word32 idx = *inOutIdx;
00504 
00505     CYASSL_ENTER("GetMyVersion");
00506 
00507     if (input[idx++] != ASN_INTEGER)
00508         return ASN_PARSE_E;
00509 
00510     if (input[idx++] != 0x01)
00511         return ASN_VERSION_E;
00512 
00513     *version  = input[idx++];
00514     *inOutIdx = idx;
00515     return *version;
00516 }
00517 
00518 
00519 #ifndef NO_PWDBASED
00520 /* Get small count integer, 32 bits or less */
00521 static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
00522 {
00523     word32 idx = *inOutIdx;
00524     word32 len;
00525 
00526     *number = 0;
00527 
00528     if (input[idx++] != ASN_INTEGER)
00529         return ASN_PARSE_E;
00530 
00531     len = input[idx++];
00532     if (len > 4)
00533         return ASN_PARSE_E;
00534 
00535     while (len--) {
00536         *number  = *number << 8 | input[idx++];
00537     }
00538 
00539     *inOutIdx = idx;
00540 
00541     return *number;
00542 }
00543 #endif /* !NO_PWDBASED */
00544 
00545 
00546 /* May not have one, not an error */
00547 static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
00548 {
00549     word32 idx = *inOutIdx;
00550 
00551     CYASSL_ENTER("GetExplicitVersion");
00552     if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
00553         *inOutIdx = ++idx;  /* eat header */
00554         return GetMyVersion(input, inOutIdx, version);
00555     }
00556 
00557     /* go back as is */
00558     *version = 0;
00559 
00560     return 0;
00561 }
00562 
00563 
00564 CYASSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
00565                   word32 maxIdx)
00566 {
00567     word32 i = *inOutIdx;
00568     byte   b = input[i++];
00569     int    length;
00570 
00571     if (b != ASN_INTEGER)
00572         return ASN_PARSE_E;
00573 
00574     if (GetLength(input, &i, &length, maxIdx) < 0)
00575         return ASN_PARSE_E;
00576 
00577     if ( (b = input[i++]) == 0x00)
00578         length--;
00579     else
00580         i--;
00581 
00582     if (mp_init(mpi) != MP_OKAY)
00583         return MP_INIT_E;
00584 
00585     if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) {
00586         mp_clear(mpi);
00587         return ASN_GETINT_E;
00588     }
00589 
00590     *inOutIdx = i + length;
00591     return 0;
00592 }
00593 
00594 
00595 static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
00596                      word32 maxIdx)
00597 {
00598     int    length;
00599     word32 i = *inOutIdx;
00600     byte   b;
00601     *oid = 0;
00602     
00603     b = input[i++];
00604     if (b != ASN_OBJECT_ID) 
00605         return ASN_OBJECT_ID_E;
00606     
00607     if (GetLength(input, &i, &length, maxIdx) < 0)
00608         return ASN_PARSE_E;
00609     
00610     while(length--)
00611         *oid += input[i++];
00612     /* just sum it up for now */
00613     
00614     *inOutIdx = i;
00615     
00616     return 0;
00617 }
00618 
00619 
00620 CYASSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
00621                      word32 maxIdx)
00622 {
00623     int    length;
00624     word32 i = *inOutIdx;
00625     byte   b;
00626     *oid = 0;
00627    
00628     CYASSL_ENTER("GetAlgoId");
00629 
00630     if (GetSequence(input, &i, &length, maxIdx) < 0)
00631         return ASN_PARSE_E;
00632     
00633     b = input[i++];
00634     if (b != ASN_OBJECT_ID) 
00635         return ASN_OBJECT_ID_E;
00636     
00637     if (GetLength(input, &i, &length, maxIdx) < 0)
00638         return ASN_PARSE_E;
00639     
00640     while(length--) {
00641         /* odd HC08 compiler behavior here when input[i++] */
00642         *oid += input[i];
00643         i++;
00644     }
00645     /* just sum it up for now */
00646     
00647     /* could have NULL tag and 0 terminator, but may not */
00648     b = input[i++];
00649     
00650     if (b == ASN_TAG_NULL) {
00651         b = input[i++];
00652         if (b != 0)
00653             return ASN_EXPECT_0_E;
00654     }
00655     else
00656     /* go back, didn't have it */
00657         i--;
00658     
00659     *inOutIdx = i;
00660     
00661     return 0;
00662 }
00663 
00664 #ifndef NO_RSA
00665 
00666 
00667 #ifdef HAVE_CAVIUM
00668 
00669 static int GetCaviumInt(byte** buff, word16* buffSz, const byte* input,
00670                         word32* inOutIdx, word32 maxIdx, void* heap)
00671 {
00672     word32 i = *inOutIdx;
00673     byte   b = input[i++];
00674     int    length;
00675 
00676     if (b != ASN_INTEGER)
00677         return ASN_PARSE_E;
00678 
00679     if (GetLength(input, &i, &length, maxIdx) < 0)
00680         return ASN_PARSE_E;
00681 
00682     if ( (b = input[i++]) == 0x00)
00683         length--;
00684     else
00685         i--;
00686 
00687     *buffSz = (word16)length;
00688     *buff   = XMALLOC(*buffSz, heap, DYNAMIC_TYPE_CAVIUM_RSA);
00689     if (*buff == NULL)
00690         return MEMORY_E;
00691 
00692     XMEMCPY(*buff, input + i, *buffSz);
00693 
00694     *inOutIdx = i + length;
00695     return 0;
00696 }
00697 
00698 static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
00699                                      RsaKey* key, word32 inSz)
00700 {
00701     int   version, length;
00702     void* h = key->heap;
00703 
00704     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
00705         return ASN_PARSE_E;
00706 
00707     if (GetMyVersion(input, inOutIdx, &version) < 0)
00708         return ASN_PARSE_E;
00709 
00710     key->type = RSA_PRIVATE;
00711 
00712     if (GetCaviumInt(&key->c_n,  &key->c_nSz,   input, inOutIdx, inSz, h) < 0 ||
00713         GetCaviumInt(&key->c_e,  &key->c_eSz,   input, inOutIdx, inSz, h) < 0 ||
00714         GetCaviumInt(&key->c_d,  &key->c_dSz,   input, inOutIdx, inSz, h) < 0 ||
00715         GetCaviumInt(&key->c_p,  &key->c_pSz,   input, inOutIdx, inSz, h) < 0 ||
00716         GetCaviumInt(&key->c_q,  &key->c_qSz,   input, inOutIdx, inSz, h) < 0 ||
00717         GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 ||
00718         GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 ||
00719         GetCaviumInt(&key->c_u,  &key->c_uSz,   input, inOutIdx, inSz, h) < 0 )
00720             return ASN_RSA_KEY_E;
00721 
00722     return 0;
00723 }
00724 
00725 
00726 #endif /* HAVE_CAVIUM */
00727 
00728 int RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
00729                         word32 inSz)
00730 {
00731     int    version, length;
00732 
00733 #ifdef HAVE_CAVIUM
00734     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00735         return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz);
00736 #endif
00737 
00738     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
00739         return ASN_PARSE_E;
00740 
00741     if (GetMyVersion(input, inOutIdx, &version) < 0)
00742         return ASN_PARSE_E;
00743 
00744     key->type = RSA_PRIVATE;
00745 
00746     if (GetInt(&key->n,  input, inOutIdx, inSz) < 0 ||
00747         GetInt(&key->e,  input, inOutIdx, inSz) < 0 ||
00748         GetInt(&key->d,  input, inOutIdx, inSz) < 0 ||
00749         GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
00750         GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
00751         GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
00752         GetInt(&key->dQ, input, inOutIdx, inSz) < 0 ||
00753         GetInt(&key->u,  input, inOutIdx, inSz) < 0 )  return ASN_RSA_KEY_E;
00754 
00755     return 0;
00756 }
00757 
00758 #endif /* NO_RSA */
00759 
00760 /* Remove PKCS8 header, move beginning of traditional to beginning of input */
00761 int ToTraditional(byte* input, word32 sz)
00762 {
00763     word32 inOutIdx = 0, oid;
00764     int    version, length;
00765 
00766     if (GetSequence(input, &inOutIdx, &length, sz) < 0)
00767         return ASN_PARSE_E;
00768 
00769     if (GetMyVersion(input, &inOutIdx, &version) < 0)
00770         return ASN_PARSE_E;
00771     
00772     if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
00773         return ASN_PARSE_E;
00774 
00775     if (input[inOutIdx] == ASN_OBJECT_ID) {
00776         /* pkcs8 ecc uses slightly different format */
00777         inOutIdx++;  /* past id */
00778         if (GetLength(input, &inOutIdx, &length, sz) < 0)
00779             return ASN_PARSE_E;
00780         inOutIdx += length;  /* over sub id, key input will verify */
00781     }
00782     
00783     if (input[inOutIdx++] != ASN_OCTET_STRING)
00784         return ASN_PARSE_E;
00785     
00786     if (GetLength(input, &inOutIdx, &length, sz) < 0)
00787         return ASN_PARSE_E;
00788     
00789     XMEMMOVE(input, input + inOutIdx, length);
00790 
00791     return length;
00792 }
00793 
00794 
00795 #ifndef NO_PWDBASED
00796 
00797 /* Check To see if PKCS version algo is supported, set id if it is return 0
00798    < 0 on error */
00799 static int CheckAlgo(int first, int second, int* id, int* version)
00800 {
00801     *id      = ALGO_ID_E;
00802     *version = PKCS5;   /* default */
00803 
00804     if (first == 1) {
00805         switch (second) {
00806         case 1:
00807             *id = PBE_SHA1_RC4_128;
00808             *version = PKCS12;
00809             return 0;
00810         case 3:
00811             *id = PBE_SHA1_DES3;
00812             *version = PKCS12;
00813             return 0;
00814         default:
00815             return ALGO_ID_E;
00816         }
00817     }
00818 
00819     if (first != PKCS5)
00820         return ASN_INPUT_E;  /* VERSION ERROR */
00821 
00822     if (second == PBES2) {
00823         *version = PKCS5v2;
00824         return 0;
00825     }
00826 
00827     switch (second) {
00828     case 3:                   /* see RFC 2898 for ids */
00829         *id = PBE_MD5_DES;
00830         return 0;
00831     case 10:
00832         *id = PBE_SHA1_DES;
00833         return 0;
00834     default:
00835         return ALGO_ID_E;
00836 
00837     }
00838 }
00839 
00840 
00841 /* Check To see if PKCS v2 algo is supported, set id if it is return 0
00842    < 0 on error */
00843 static int CheckAlgoV2(int oid, int* id)
00844 {
00845     switch (oid) {
00846     case 69:
00847         *id = PBE_SHA1_DES;
00848         return 0;
00849     case 652:
00850         *id = PBE_SHA1_DES3;
00851         return 0;
00852     default:
00853         return ALGO_ID_E;
00854 
00855     }
00856 }
00857 
00858 
00859 /* Decrypt intput in place from parameters based on id */
00860 static int DecryptKey(const char* password, int passwordSz, byte* salt,
00861                       int saltSz, int iterations, int id, byte* input,
00862                       int length, int version, byte* cbcIv)
00863 {
00864     int typeH;
00865     int derivedLen;
00866     int decryptionType;
00867     int ret = 0;
00868 #ifdef CYASSL_SMALL_STACK
00869     byte* key;
00870 #else
00871     byte key[MAX_KEY_SIZE];
00872 #endif
00873 
00874     switch (id) {
00875         case PBE_MD5_DES:
00876             typeH = MD5;
00877             derivedLen = 16;           /* may need iv for v1.5 */
00878             decryptionType = DES_TYPE;
00879             break;
00880 
00881         case PBE_SHA1_DES:
00882             typeH = SHA;
00883             derivedLen = 16;           /* may need iv for v1.5 */
00884             decryptionType = DES_TYPE;
00885             break;
00886 
00887         case PBE_SHA1_DES3:
00888             typeH = SHA;
00889             derivedLen = 32;           /* may need iv for v1.5 */
00890             decryptionType = DES3_TYPE;
00891             break;
00892 
00893         case PBE_SHA1_RC4_128:
00894             typeH = SHA;
00895             derivedLen = 16;
00896             decryptionType = RC4_TYPE;
00897             break;
00898 
00899         default:
00900             return ALGO_ID_E;
00901     }
00902 
00903 #ifdef CYASSL_SMALL_STACK
00904     key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00905     if (key == NULL)
00906         return MEMORY_E;
00907 #endif
00908 
00909     if (version == PKCS5v2)
00910         ret = PBKDF2(key, (byte*)password, passwordSz, salt, saltSz, iterations,
00911                derivedLen, typeH);
00912     else if (version == PKCS5)
00913         ret = PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations,
00914                derivedLen, typeH);
00915     else if (version == PKCS12) {
00916         int  i, idx = 0;
00917         byte unicodePasswd[MAX_UNICODE_SZ];
00918 
00919         if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
00920 #ifdef CYASSL_SMALL_STACK
00921             XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00922 #endif
00923             return UNICODE_SIZE_E; 
00924         }
00925 
00926         for (i = 0; i < passwordSz; i++) {
00927             unicodePasswd[idx++] = 0x00;
00928             unicodePasswd[idx++] = (byte)password[i];
00929         }
00930         /* add trailing NULL */
00931         unicodePasswd[idx++] = 0x00;
00932         unicodePasswd[idx++] = 0x00;
00933 
00934         ret =  PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz,
00935                             iterations, derivedLen, typeH, 1);
00936         if (decryptionType != RC4_TYPE)
00937             ret += PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz,
00938                                 iterations, 8, typeH, 2);
00939     }
00940     else {
00941 #ifdef CYASSL_SMALL_STACK
00942         XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00943 #endif
00944         return ALGO_ID_E;
00945     }
00946 
00947     if (ret != 0) {
00948 #ifdef CYASSL_SMALL_STACK
00949         XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00950 #endif
00951         return ret;
00952     }
00953 
00954     switch (decryptionType) {
00955 #ifndef NO_DES3
00956         case DES_TYPE:
00957         {
00958             Des    dec;
00959             byte*  desIv = key + 8;
00960 
00961             if (version == PKCS5v2 || version == PKCS12)
00962                 desIv = cbcIv;
00963 
00964             ret = Des_SetKey(&dec, key, desIv, DES_DECRYPTION);
00965             if (ret != 0) {
00966 #ifdef CYASSL_SMALL_STACK
00967                 XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00968 #endif
00969                 return ret;
00970             }
00971 
00972             Des_CbcDecrypt(&dec, input, input, length);
00973             break;
00974         }
00975 
00976         case DES3_TYPE:
00977         {
00978             Des3   dec;
00979             byte*  desIv = key + 24;
00980 
00981             if (version == PKCS5v2 || version == PKCS12)
00982                 desIv = cbcIv;
00983             ret = Des3_SetKey(&dec, key, desIv, DES_DECRYPTION);
00984             if (ret != 0) {
00985 #ifdef CYASSL_SMALL_STACK
00986                 XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00987 #endif
00988                 return ret;
00989             }
00990             ret = Des3_CbcDecrypt(&dec, input, input, length);
00991             if (ret != 0) {
00992 #ifdef CYASSL_SMALL_STACK
00993                 XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00994 #endif
00995                 return ret;
00996             }
00997             break;
00998         }
00999 #endif
01000 #ifndef NO_RC4
01001         case RC4_TYPE:
01002         {
01003             Arc4    dec;
01004 
01005             Arc4SetKey(&dec, key, derivedLen);
01006             Arc4Process(&dec, input, input, length);
01007             break;
01008         }
01009 #endif
01010 
01011         default:
01012 #ifdef CYASSL_SMALL_STACK
01013             XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01014 #endif
01015             return ALGO_ID_E; 
01016     }
01017 
01018 #ifdef CYASSL_SMALL_STACK
01019     XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01020 #endif
01021 
01022     return 0;
01023 }
01024 
01025 
01026 /* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
01027    of input */
01028 int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
01029 {
01030     word32 inOutIdx = 0, oid;
01031     int    first, second, length, version, saltSz, id;
01032     int    iterations = 0;
01033 #ifdef CYASSL_SMALL_STACK
01034     byte*  salt = NULL;
01035     byte*  cbcIv = NULL;
01036 #else
01037     byte   salt[MAX_SALT_SIZE];
01038     byte   cbcIv[MAX_IV_SIZE];
01039 #endif
01040     
01041     if (GetSequence(input, &inOutIdx, &length, sz) < 0)
01042         return ASN_PARSE_E;
01043 
01044     if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
01045         return ASN_PARSE_E;
01046     
01047     first  = input[inOutIdx - 2];   /* PKCS version alwyas 2nd to last byte */
01048     second = input[inOutIdx - 1];   /* version.algo, algo id last byte */
01049 
01050     if (CheckAlgo(first, second, &id, &version) < 0)
01051         return ASN_INPUT_E;  /* Algo ID error */
01052 
01053     if (version == PKCS5v2) {
01054 
01055         if (GetSequence(input, &inOutIdx, &length, sz) < 0)
01056             return ASN_PARSE_E;
01057 
01058         if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
01059             return ASN_PARSE_E;
01060 
01061         if (oid != PBKDF2_OID)
01062             return ASN_PARSE_E;
01063     }
01064 
01065     if (GetSequence(input, &inOutIdx, &length, sz) < 0)
01066         return ASN_PARSE_E;
01067 
01068     if (input[inOutIdx++] != ASN_OCTET_STRING)
01069         return ASN_PARSE_E;
01070     
01071     if (GetLength(input, &inOutIdx, &saltSz, sz) < 0)
01072         return ASN_PARSE_E;
01073 
01074     if (saltSz > MAX_SALT_SIZE)
01075         return ASN_PARSE_E;
01076      
01077 #ifdef CYASSL_SMALL_STACK
01078     salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01079     if (salt == NULL)
01080         return MEMORY_E;
01081 #endif
01082 
01083     XMEMCPY(salt, &input[inOutIdx], saltSz);
01084     inOutIdx += saltSz;
01085 
01086     if (GetShortInt(input, &inOutIdx, &iterations) < 0) {
01087 #ifdef CYASSL_SMALL_STACK
01088         XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01089 #endif
01090         return ASN_PARSE_E;
01091     }
01092 
01093 #ifdef CYASSL_SMALL_STACK
01094     cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01095     if (cbcIv == NULL) {
01096         XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01097         return MEMORY_E;
01098     }
01099 #endif
01100 
01101     if (version == PKCS5v2) {
01102         /* get encryption algo */
01103         if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) {
01104 #ifdef CYASSL_SMALL_STACK
01105             XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01106             XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01107 #endif
01108             return ASN_PARSE_E;
01109         }
01110 
01111         if (CheckAlgoV2(oid, &id) < 0) {
01112 #ifdef CYASSL_SMALL_STACK
01113             XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01114             XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01115 #endif
01116             return ASN_PARSE_E;  /* PKCS v2 algo id error */
01117         }
01118 
01119         if (input[inOutIdx++] != ASN_OCTET_STRING) {
01120 #ifdef CYASSL_SMALL_STACK
01121             XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01122             XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01123 #endif
01124             return ASN_PARSE_E;
01125         }
01126     
01127         if (GetLength(input, &inOutIdx, &length, sz) < 0) {
01128 #ifdef CYASSL_SMALL_STACK
01129             XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01130             XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01131 #endif
01132             return ASN_PARSE_E;
01133         }
01134 
01135         XMEMCPY(cbcIv, &input[inOutIdx], length);
01136         inOutIdx += length;
01137     }
01138 
01139     if (input[inOutIdx++] != ASN_OCTET_STRING) {
01140 #ifdef CYASSL_SMALL_STACK
01141         XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01142         XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01143 #endif
01144         return ASN_PARSE_E;
01145     }
01146 
01147     if (GetLength(input, &inOutIdx, &length, sz) < 0) {
01148 #ifdef CYASSL_SMALL_STACK
01149         XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01150         XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01151 #endif
01152         return ASN_PARSE_E;
01153     }
01154 
01155     if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id,
01156                    input + inOutIdx, length, version, cbcIv) < 0) {
01157 #ifdef CYASSL_SMALL_STACK
01158         XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01159         XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01160 #endif
01161         return ASN_INPUT_E;  /* decrypt failure */
01162     }
01163 
01164 #ifdef CYASSL_SMALL_STACK
01165     XFREE(salt,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
01166     XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01167 #endif
01168 
01169     XMEMMOVE(input, input + inOutIdx, length);
01170     return ToTraditional(input, length);
01171 }
01172 
01173 #endif /* NO_PWDBASED */
01174 
01175 #ifndef NO_RSA
01176 
01177 int RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
01178                        word32 inSz)
01179 {
01180     int    length;
01181 
01182     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
01183         return ASN_PARSE_E;
01184 
01185     key->type = RSA_PUBLIC;
01186 
01187 #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
01188     {
01189     byte b = input[*inOutIdx];
01190     if (b != ASN_INTEGER) {
01191         /* not from decoded cert, will have algo id, skip past */
01192         if (GetSequence(input, inOutIdx, &length, inSz) < 0)
01193             return ASN_PARSE_E;
01194         
01195         b = input[(*inOutIdx)++];
01196         if (b != ASN_OBJECT_ID) 
01197             return ASN_OBJECT_ID_E;
01198         
01199         if (GetLength(input, inOutIdx, &length, inSz) < 0)
01200             return ASN_PARSE_E;
01201         
01202         *inOutIdx += length;   /* skip past */
01203         
01204         /* could have NULL tag and 0 terminator, but may not */
01205         b = input[(*inOutIdx)++];
01206         
01207         if (b == ASN_TAG_NULL) {
01208             b = input[(*inOutIdx)++];
01209             if (b != 0) 
01210                 return ASN_EXPECT_0_E;
01211         }
01212         else
01213         /* go back, didn't have it */
01214             (*inOutIdx)--;
01215         
01216         /* should have bit tag length and seq next */
01217         b = input[(*inOutIdx)++];
01218         if (b != ASN_BIT_STRING)
01219             return ASN_BITSTR_E;
01220         
01221         if (GetLength(input, inOutIdx, &length, inSz) < 0)
01222             return ASN_PARSE_E;
01223         
01224         /* could have 0 */
01225         b = input[(*inOutIdx)++];
01226         if (b != 0)
01227             (*inOutIdx)--;
01228         
01229         if (GetSequence(input, inOutIdx, &length, inSz) < 0)
01230             return ASN_PARSE_E;
01231     }  /* end if */
01232     }  /* openssl var block */
01233 #endif /* OPENSSL_EXTRA */
01234 
01235     if (GetInt(&key->n,  input, inOutIdx, inSz) < 0 ||
01236         GetInt(&key->e,  input, inOutIdx, inSz) < 0 )  return ASN_RSA_KEY_E;
01237 
01238     return 0;
01239 }
01240 
01241 int RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, word32 eSz,
01242                           RsaKey* key)
01243 {
01244     if (n == NULL || e == NULL || key == NULL)
01245         return BAD_FUNC_ARG;
01246 
01247     key->type = RSA_PUBLIC;
01248 
01249     if (mp_init(&key->n) != MP_OKAY)
01250         return MP_INIT_E;
01251 
01252     if (mp_read_unsigned_bin(&key->n, n, nSz) != 0) {
01253         mp_clear(&key->n);
01254         return ASN_GETINT_E;
01255     }
01256 
01257     if (mp_init(&key->e) != MP_OKAY) {
01258         mp_clear(&key->n);
01259         return MP_INIT_E;
01260     }
01261 
01262     if (mp_read_unsigned_bin(&key->e, e, eSz) != 0) {
01263         mp_clear(&key->n);
01264         mp_clear(&key->e);
01265         return ASN_GETINT_E;
01266     }
01267 
01268     return 0;
01269 }
01270 
01271 #endif
01272 
01273 #ifndef NO_DH
01274 
01275 int DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
01276 {
01277     int    length;
01278 
01279     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
01280         return ASN_PARSE_E;
01281 
01282     if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
01283         GetInt(&key->g,  input, inOutIdx, inSz) < 0 )  return ASN_DH_KEY_E;
01284 
01285     return 0;
01286 }
01287 
01288 int DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz)
01289 {
01290     if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0)
01291         return BAD_FUNC_ARG;
01292 
01293     /* may have leading 0 */
01294     if (p[0] == 0) {
01295         pSz--; p++;
01296     }
01297 
01298     if (g[0] == 0) {
01299         gSz--; g++;
01300     }
01301 
01302     if (mp_init(&key->p) != MP_OKAY)
01303         return MP_INIT_E;
01304     if (mp_read_unsigned_bin(&key->p, p, pSz) != 0) {
01305         mp_clear(&key->p);
01306         return ASN_DH_KEY_E;
01307     }
01308 
01309     if (mp_init(&key->g) != MP_OKAY) {
01310         mp_clear(&key->p);
01311         return MP_INIT_E;
01312     }
01313     if (mp_read_unsigned_bin(&key->g, g, gSz) != 0) {
01314         mp_clear(&key->g);
01315         mp_clear(&key->p);
01316         return ASN_DH_KEY_E;
01317     }
01318 
01319     return 0;
01320 }
01321 
01322 
01323 int DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
01324                  byte* g, word32* gInOutSz)
01325 {
01326     word32 i = 0;
01327     byte   b;
01328     int    length;
01329 
01330     if (GetSequence(input, &i, &length, inSz) < 0)
01331         return ASN_PARSE_E;
01332 
01333     b = input[i++];
01334     if (b != ASN_INTEGER)
01335         return ASN_PARSE_E;
01336 
01337     if (GetLength(input, &i, &length, inSz) < 0)
01338         return ASN_PARSE_E;
01339 
01340     if ( (b = input[i++]) == 0x00)
01341         length--;
01342     else
01343         i--;
01344 
01345     if (length <= (int)*pInOutSz) {
01346         XMEMCPY(p, &input[i], length);
01347         *pInOutSz = length;
01348     }
01349     else
01350         return BUFFER_E;
01351 
01352     i += length;
01353 
01354     b = input[i++];
01355     if (b != ASN_INTEGER)
01356         return ASN_PARSE_E;
01357 
01358     if (GetLength(input, &i, &length, inSz) < 0)
01359         return ASN_PARSE_E;
01360 
01361     if (length <= (int)*gInOutSz) {
01362         XMEMCPY(g, &input[i], length);
01363         *gInOutSz = length;
01364     }
01365     else
01366         return BUFFER_E;
01367 
01368     return 0;
01369 }
01370 
01371 #endif /* NO_DH */
01372 
01373 
01374 #ifndef NO_DSA
01375 
01376 int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
01377                         word32 inSz)
01378 {
01379     int    length;
01380 
01381     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
01382         return ASN_PARSE_E;
01383 
01384     if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
01385         GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
01386         GetInt(&key->g,  input, inOutIdx, inSz) < 0 ||
01387         GetInt(&key->y,  input, inOutIdx, inSz) < 0 )  return ASN_DH_KEY_E;
01388 
01389     key->type = DSA_PUBLIC;
01390     return 0;
01391 }
01392 
01393 
01394 int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
01395                         word32 inSz)
01396 {
01397     int    length, version;
01398 
01399     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
01400         return ASN_PARSE_E;
01401 
01402     if (GetMyVersion(input, inOutIdx, &version) < 0)
01403         return ASN_PARSE_E;
01404 
01405     if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
01406         GetInt(&key->q,  input, inOutIdx, inSz) < 0 ||
01407         GetInt(&key->g,  input, inOutIdx, inSz) < 0 ||
01408         GetInt(&key->y,  input, inOutIdx, inSz) < 0 ||
01409         GetInt(&key->x,  input, inOutIdx, inSz) < 0 )  return ASN_DH_KEY_E;
01410 
01411     key->type = DSA_PRIVATE;
01412     return 0;
01413 }
01414 
01415 #endif /* NO_DSA */
01416 
01417 
01418 void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
01419 {
01420     cert->publicKey       = 0;
01421     cert->pubKeySize      = 0;
01422     cert->pubKeyStored    = 0;
01423     cert->version         = 0;
01424     cert->signature       = 0;
01425     cert->subjectCN       = 0;
01426     cert->subjectCNLen    = 0;
01427     cert->subjectCNEnc    = CTC_UTF8;
01428     cert->subjectCNStored = 0;
01429     cert->altNames        = NULL;
01430 #ifndef IGNORE_NAME_CONSTRAINTS
01431     cert->altEmailNames   = NULL;
01432     cert->permittedNames  = NULL;
01433     cert->excludedNames   = NULL;
01434 #endif /* IGNORE_NAME_CONSTRAINTS */
01435     cert->issuer[0]       = '\0';
01436     cert->subject[0]      = '\0';
01437     cert->source          = source;  /* don't own */
01438     cert->srcIdx          = 0;
01439     cert->maxIdx          = inSz;    /* can't go over this index */
01440     cert->heap            = heap;
01441     XMEMSET(cert->serial, 0, EXTERNAL_SERIAL_SIZE);
01442     cert->serialSz        = 0;
01443     cert->extensions      = 0;
01444     cert->extensionsSz    = 0;
01445     cert->extensionsIdx   = 0;
01446     cert->extAuthInfo     = NULL;
01447     cert->extAuthInfoSz   = 0;
01448     cert->extCrlInfo      = NULL;
01449     cert->extCrlInfoSz    = 0;
01450     XMEMSET(cert->extSubjKeyId, 0, SHA_SIZE);
01451     cert->extSubjKeyIdSet = 0;
01452     XMEMSET(cert->extAuthKeyId, 0, SHA_SIZE);
01453     cert->extAuthKeyIdSet = 0;
01454     cert->extKeyUsageSet  = 0;
01455     cert->extKeyUsage     = 0;
01456     cert->extExtKeyUsageSet = 0;
01457     cert->extExtKeyUsage    = 0;
01458     cert->isCA            = 0;
01459 #ifdef HAVE_PKCS7
01460     cert->issuerRaw       = NULL;
01461     cert->issuerRawLen    = 0;
01462 #endif
01463 #ifdef CYASSL_CERT_GEN
01464     cert->subjectSN       = 0;
01465     cert->subjectSNLen    = 0;
01466     cert->subjectSNEnc    = CTC_UTF8;
01467     cert->subjectC        = 0;
01468     cert->subjectCLen     = 0;
01469     cert->subjectCEnc     = CTC_PRINTABLE;
01470     cert->subjectL        = 0;
01471     cert->subjectLLen     = 0;
01472     cert->subjectLEnc     = CTC_UTF8;
01473     cert->subjectST       = 0;
01474     cert->subjectSTLen    = 0;
01475     cert->subjectSTEnc    = CTC_UTF8;
01476     cert->subjectO        = 0;
01477     cert->subjectOLen     = 0;
01478     cert->subjectOEnc     = CTC_UTF8;
01479     cert->subjectOU       = 0;
01480     cert->subjectOULen    = 0;
01481     cert->subjectOUEnc    = CTC_UTF8;
01482     cert->subjectEmail    = 0;
01483     cert->subjectEmailLen = 0;
01484 #endif /* CYASSL_CERT_GEN */
01485     cert->beforeDate      = NULL;
01486     cert->beforeDateLen   = 0;
01487     cert->afterDate       = NULL;
01488     cert->afterDateLen    = 0;
01489 #ifdef OPENSSL_EXTRA
01490     XMEMSET(&cert->issuerName, 0, sizeof(DecodedName));
01491     XMEMSET(&cert->subjectName, 0, sizeof(DecodedName));
01492     cert->extBasicConstSet = 0;
01493     cert->extBasicConstCrit = 0;
01494     cert->extBasicConstPlSet = 0;
01495     cert->pathLength = 0;
01496     cert->extSubjAltNameSet = 0;
01497     cert->extSubjAltNameCrit = 0;
01498     cert->extAuthKeyIdCrit = 0;
01499     cert->extSubjKeyIdCrit = 0;
01500     cert->extKeyUsageCrit = 0;
01501     cert->extExtKeyUsageCrit = 0;
01502     cert->extExtKeyUsageSrc = NULL;
01503     cert->extExtKeyUsageSz = 0;
01504     cert->extExtKeyUsageCount = 0;
01505     cert->extAuthKeyIdSrc = NULL;
01506     cert->extAuthKeyIdSz = 0;
01507     cert->extSubjKeyIdSrc = NULL;
01508     cert->extSubjKeyIdSz = 0;
01509 #endif /* OPENSSL_EXTRA */
01510 #if defined(OPENSSL_EXTRA) || !defined(IGNORE_NAME_CONSTRAINTS)
01511     cert->extNameConstraintSet = 0;
01512 #endif /* OPENSSL_EXTRA || !IGNORE_NAME_CONSTRAINTS */
01513 #ifdef HAVE_ECC
01514     cert->pkCurveOID = 0;
01515 #endif /* HAVE_ECC */
01516 #ifdef CYASSL_SEP
01517     cert->deviceTypeSz = 0;
01518     cert->deviceType = NULL;
01519     cert->hwTypeSz = 0;
01520     cert->hwType = NULL;
01521     cert->hwSerialNumSz = 0;
01522     cert->hwSerialNum = NULL;
01523     #ifdef OPENSSL_EXTRA
01524         cert->extCertPolicySet = 0;
01525         cert->extCertPolicyCrit = 0;
01526     #endif /* OPENSSL_EXTRA */
01527 #endif /* CYASSL_SEP */
01528 }
01529 
01530 
01531 void FreeAltNames(DNS_entry* altNames, void* heap)
01532 {
01533     (void)heap;
01534 
01535     while (altNames) {
01536         DNS_entry* tmp = altNames->next;
01537 
01538         XFREE(altNames->name, heap, DYNAMIC_TYPE_ALTNAME);
01539         XFREE(altNames,       heap, DYNAMIC_TYPE_ALTNAME);
01540         altNames = tmp;
01541     }
01542 }
01543 
01544 #ifndef IGNORE_NAME_CONSTRAINTS
01545 
01546 void FreeNameSubtrees(Base_entry* names, void* heap)
01547 {
01548     (void)heap;
01549 
01550     while (names) {
01551         Base_entry* tmp = names->next;
01552 
01553         XFREE(names->name, heap, DYNAMIC_TYPE_ALTNAME);
01554         XFREE(names,       heap, DYNAMIC_TYPE_ALTNAME);
01555         names = tmp;
01556     }
01557 }
01558 
01559 #endif /* IGNORE_NAME_CONSTRAINTS */
01560 
01561 void FreeDecodedCert(DecodedCert* cert)
01562 {
01563     if (cert->subjectCNStored == 1)
01564         XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
01565     if (cert->pubKeyStored == 1)
01566         XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
01567     if (cert->altNames)
01568         FreeAltNames(cert->altNames, cert->heap);
01569 #ifndef IGNORE_NAME_CONSTRAINTS
01570     if (cert->altEmailNames)
01571         FreeAltNames(cert->altEmailNames, cert->heap);
01572     if (cert->permittedNames)
01573         FreeNameSubtrees(cert->permittedNames, cert->heap);
01574     if (cert->excludedNames)
01575         FreeNameSubtrees(cert->excludedNames, cert->heap);
01576 #endif /* IGNORE_NAME_CONSTRAINTS */
01577 #ifdef CYASSL_SEP
01578     XFREE(cert->deviceType, cert->heap, 0);
01579     XFREE(cert->hwType, cert->heap, 0);
01580     XFREE(cert->hwSerialNum, cert->heap, 0);
01581 #endif /* CYASSL_SEP */
01582 #ifdef OPENSSL_EXTRA
01583     if (cert->issuerName.fullName != NULL)
01584         XFREE(cert->issuerName.fullName, NULL, DYNAMIC_TYPE_X509);
01585     if (cert->subjectName.fullName != NULL)
01586         XFREE(cert->subjectName.fullName, NULL, DYNAMIC_TYPE_X509);
01587 #endif /* OPENSSL_EXTRA */
01588 }
01589 
01590 
01591 static int GetCertHeader(DecodedCert* cert)
01592 {
01593     int ret = 0, len;
01594     byte serialTmp[EXTERNAL_SERIAL_SIZE];
01595 #if defined(CYASSL_SMALL_STACK) && defined(USE_FAST_MATH)
01596     mp_int* mpi = NULL;
01597 #else
01598     mp_int stack_mpi;
01599     mp_int* mpi = &stack_mpi;
01600 #endif
01601 
01602     if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
01603         return ASN_PARSE_E;
01604 
01605     cert->certBegin = cert->srcIdx;
01606 
01607     if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
01608         return ASN_PARSE_E;
01609     cert->sigIndex = len + cert->srcIdx;
01610 
01611     if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version) < 0)
01612         return ASN_PARSE_E;
01613 
01614 #if defined(CYASSL_SMALL_STACK) && defined(USE_FAST_MATH)
01615     mpi = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER);
01616     if (mpi == NULL)
01617         return MEMORY_E;
01618 #endif
01619 
01620     if (GetInt(mpi, cert->source, &cert->srcIdx, cert->maxIdx) < 0) {
01621 #if defined(CYASSL_SMALL_STACK) && defined(USE_FAST_MATH)
01622         XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01623 #endif
01624         return ASN_PARSE_E;
01625     }
01626 
01627     len = mp_unsigned_bin_size(mpi);
01628     if (len < (int)sizeof(serialTmp)) {
01629         if ( (ret = mp_to_unsigned_bin(mpi, serialTmp)) == MP_OKAY) {
01630             XMEMCPY(cert->serial, serialTmp, len);
01631             cert->serialSz = len;
01632         }
01633     }
01634     mp_clear(mpi);
01635 
01636 #if defined(CYASSL_SMALL_STACK) && defined(USE_FAST_MATH)
01637     XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01638 #endif
01639 
01640     return ret;
01641 }
01642 
01643 #if !defined(NO_RSA)
01644 /* Store Rsa Key, may save later, Dsa could use in future */
01645 static int StoreRsaKey(DecodedCert* cert)
01646 {
01647     int    length;
01648     word32 recvd = cert->srcIdx;
01649 
01650     if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
01651         return ASN_PARSE_E;
01652    
01653     recvd = cert->srcIdx - recvd;
01654     length += recvd;
01655 
01656     while (recvd--)
01657        cert->srcIdx--;
01658 
01659     cert->pubKeySize = length;
01660     cert->publicKey = cert->source + cert->srcIdx;
01661     cert->srcIdx += length;
01662 
01663     return 0;
01664 }
01665 #endif
01666 
01667 
01668 #ifdef HAVE_ECC
01669 
01670     /* return 0 on sucess if the ECC curve oid sum is supported */
01671     static int CheckCurve(word32 oid)
01672     {
01673         if (oid != ECC_256R1 && oid != ECC_384R1 && oid != ECC_521R1 && oid !=
01674                    ECC_160R1 && oid != ECC_192R1 && oid != ECC_224R1)
01675             return ALGO_ID_E; 
01676 
01677         return 0;
01678     }
01679 
01680 #endif /* HAVE_ECC */
01681 
01682 
01683 static int GetKey(DecodedCert* cert)
01684 {
01685     int length;
01686 #ifdef HAVE_NTRU
01687     int tmpIdx = cert->srcIdx;
01688 #endif
01689 
01690     if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
01691         return ASN_PARSE_E;
01692    
01693     if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID, cert->maxIdx) < 0)
01694         return ASN_PARSE_E;
01695 
01696     switch (cert->keyOID) {
01697    #ifndef NO_RSA
01698         case RSAk:
01699         {
01700             byte b = cert->source[cert->srcIdx++];
01701             if (b != ASN_BIT_STRING)
01702                 return ASN_BITSTR_E;
01703 
01704             if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
01705                 return ASN_PARSE_E;
01706             b = cert->source[cert->srcIdx++];
01707             if (b != 0x00)
01708                 return ASN_EXPECT_0_E;
01709     
01710             return StoreRsaKey(cert);
01711         }
01712 
01713     #endif /* NO_RSA */
01714     #ifdef HAVE_NTRU
01715         case NTRUk:
01716         {
01717             const byte* key = &cert->source[tmpIdx];
01718             byte*       next = (byte*)key;
01719             word16      keyLen;
01720             word32      rc;
01721             word32      remaining = cert->maxIdx - cert->srcIdx;
01722 #ifdef CYASSL_SMALL_STACK
01723             byte*       keyBlob = NULL;
01724 #else
01725             byte        keyBlob[MAX_NTRU_KEY_SZ];
01726 #endif
01727             rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
01728                                 &keyLen, NULL, &next, &remaining);
01729             if (rc != NTRU_OK)
01730                 return ASN_NTRU_KEY_E;
01731             if (keyLen > MAX_NTRU_KEY_SZ)
01732                 return ASN_NTRU_KEY_E;
01733 
01734 #ifdef CYASSL_SMALL_STACK
01735             keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, NULL,
01736                                                        DYNAMIC_TYPE_TMP_BUFFER);
01737             if (keyBlob == NULL)
01738                 return MEMORY_E;
01739 #endif
01740 
01741             rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
01742                                 &keyLen, keyBlob, &next, &remaining);
01743             if (rc != NTRU_OK) {
01744 #ifdef CYASSL_SMALL_STACK
01745                 XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01746 #endif
01747                 return ASN_NTRU_KEY_E;
01748             }
01749 
01750             if ( (next - key) < 0) {
01751 #ifdef CYASSL_SMALL_STACK
01752                 XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01753 #endif
01754                 return ASN_NTRU_KEY_E;
01755             }
01756 
01757             cert->srcIdx = tmpIdx + (int)(next - key);
01758 
01759             cert->publicKey = (byte*) XMALLOC(keyLen, cert->heap,
01760                                               DYNAMIC_TYPE_PUBLIC_KEY);
01761             if (cert->publicKey == NULL) {
01762 #ifdef CYASSL_SMALL_STACK
01763                 XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01764 #endif
01765                 return MEMORY_E;
01766             }
01767             XMEMCPY(cert->publicKey, keyBlob, keyLen);
01768             cert->pubKeyStored = 1;
01769             cert->pubKeySize   = keyLen;
01770 
01771 #ifdef CYASSL_SMALL_STACK
01772             XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01773 #endif
01774 
01775             return 0;
01776         }
01777     #endif /* HAVE_NTRU */
01778     #ifdef HAVE_ECC
01779         case ECDSAk:
01780         {
01781             int    oidSz = 0;
01782             byte   b = cert->source[cert->srcIdx++];
01783         
01784             if (b != ASN_OBJECT_ID) 
01785                 return ASN_OBJECT_ID_E;
01786 
01787             if (GetLength(cert->source,&cert->srcIdx,&oidSz,cert->maxIdx) < 0)
01788                 return ASN_PARSE_E;
01789 
01790             while(oidSz--)
01791                 cert->pkCurveOID += cert->source[cert->srcIdx++];
01792 
01793             if (CheckCurve(cert->pkCurveOID) < 0)
01794                 return ECC_CURVE_OID_E;
01795 
01796             /* key header */
01797             b = cert->source[cert->srcIdx++];
01798             if (b != ASN_BIT_STRING)
01799                 return ASN_BITSTR_E;
01800 
01801             if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
01802                 return ASN_PARSE_E;
01803             b = cert->source[cert->srcIdx++];
01804             if (b != 0x00)
01805                 return ASN_EXPECT_0_E;
01806 
01807             /* actual key, use length - 1 since ate preceding 0 */
01808             length -= 1;
01809 
01810             cert->publicKey = (byte*) XMALLOC(length, cert->heap,
01811                                               DYNAMIC_TYPE_PUBLIC_KEY);
01812             if (cert->publicKey == NULL)
01813                 return MEMORY_E;
01814             XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length);
01815             cert->pubKeyStored = 1;
01816             cert->pubKeySize   = length;
01817 
01818             cert->srcIdx += length;
01819 
01820             return 0;
01821         }
01822     #endif /* HAVE_ECC */
01823         default:
01824             return ASN_UNKNOWN_OID_E;
01825     }
01826 }
01827 
01828 
01829 /* process NAME, either issuer or subject */
01830 static int GetName(DecodedCert* cert, int nameType)
01831 {
01832     Sha    sha;     /* MUST have SHA-1 hash for cert names */
01833     int    length;  /* length of all distinguished names */
01834     int    dummy;
01835     int    ret;
01836     char* full = (nameType == ISSUER) ? cert->issuer : cert->subject;
01837     word32 idx;
01838     #ifdef OPENSSL_EXTRA
01839         DecodedName* dName =
01840                   (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName;
01841     #endif /* OPENSSL_EXTRA */
01842 
01843     CYASSL_MSG("Getting Cert Name");
01844 
01845     if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) {
01846         CYASSL_MSG("Trying optional prefix...");
01847 
01848         if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
01849             return ASN_PARSE_E;
01850 
01851         cert->srcIdx += length;
01852         CYASSL_MSG("Got optional prefix");
01853     }
01854 
01855     /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
01856      * calculated over the entire DER encoding of the Name field, including
01857      * the tag and length. */
01858     idx = cert->srcIdx;
01859     if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
01860         return ASN_PARSE_E;
01861 
01862     ret = InitSha(&sha);
01863     if (ret != 0)
01864         return ret;
01865     ShaUpdate(&sha, &cert->source[idx], length + cert->srcIdx - idx);
01866     if (nameType == ISSUER)
01867         ShaFinal(&sha, cert->issuerHash);
01868     else
01869         ShaFinal(&sha, cert->subjectHash);
01870 
01871     length += cert->srcIdx;
01872     idx = 0;
01873 
01874 #ifdef HAVE_PKCS7
01875     /* store pointer to raw issuer */
01876     if (nameType == ISSUER) {
01877         cert->issuerRaw = &cert->source[cert->srcIdx];
01878         cert->issuerRawLen = length - cert->srcIdx;
01879     }
01880 #endif
01881 #ifndef IGNORE_NAME_CONSTRAINTS
01882     if (nameType == SUBJECT) {
01883         cert->subjectRaw = &cert->source[cert->srcIdx];
01884         cert->subjectRawLen = length - cert->srcIdx;
01885     }
01886 #endif
01887 
01888     while (cert->srcIdx < (word32)length) {
01889         byte   b;
01890         byte   joint[2];
01891         byte   tooBig = FALSE;
01892         int    oidSz;
01893 
01894         if (GetSet(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) {
01895             CYASSL_MSG("Cert name lacks set header, trying sequence");
01896         }
01897 
01898         if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0)
01899             return ASN_PARSE_E;
01900 
01901         b = cert->source[cert->srcIdx++];
01902         if (b != ASN_OBJECT_ID) 
01903             return ASN_OBJECT_ID_E;
01904 
01905         if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0)
01906             return ASN_PARSE_E;
01907 
01908         XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
01909 
01910         /* v1 name types */
01911         if (joint[0] == 0x55 && joint[1] == 0x04) {
01912             byte   id;
01913             byte   copy = FALSE;
01914             int    strLen;
01915 
01916             cert->srcIdx += 2;
01917             id = cert->source[cert->srcIdx++]; 
01918             b  = cert->source[cert->srcIdx++]; /* encoding */
01919 
01920             if (GetLength(cert->source, &cert->srcIdx, &strLen,
01921                           cert->maxIdx) < 0)
01922                 return ASN_PARSE_E;
01923 
01924             if ( (strLen + 14) > (int)(ASN_NAME_MAX - idx)) {
01925                 /* include biggest pre fix header too 4 = "/serialNumber=" */
01926                 CYASSL_MSG("ASN Name too big, skipping");
01927                 tooBig = TRUE;
01928             }
01929 
01930             if (id == ASN_COMMON_NAME) {
01931                 if (nameType == SUBJECT) {
01932                     cert->subjectCN = (char *)&cert->source[cert->srcIdx];
01933                     cert->subjectCNLen = strLen;
01934                     cert->subjectCNEnc = b;
01935                 }
01936 
01937                 if (!tooBig) {
01938                     XMEMCPY(&full[idx], "/CN=", 4);
01939                     idx += 4;
01940                     copy = TRUE;
01941                 }
01942                 #ifdef OPENSSL_EXTRA
01943                     dName->cnIdx = cert->srcIdx;
01944                     dName->cnLen = strLen;
01945                 #endif /* OPENSSL_EXTRA */
01946             }
01947             else if (id == ASN_SUR_NAME) {
01948                 if (!tooBig) {
01949                     XMEMCPY(&full[idx], "/SN=", 4);
01950                     idx += 4;
01951                     copy = TRUE;
01952                 }
01953                 #ifdef CYASSL_CERT_GEN
01954                     if (nameType == SUBJECT) {
01955                         cert->subjectSN = (char*)&cert->source[cert->srcIdx];
01956                         cert->subjectSNLen = strLen;
01957                         cert->subjectSNEnc = b;
01958                     }
01959                 #endif /* CYASSL_CERT_GEN */
01960                 #ifdef OPENSSL_EXTRA
01961                     dName->snIdx = cert->srcIdx;
01962                     dName->snLen = strLen;
01963                 #endif /* OPENSSL_EXTRA */
01964             }
01965             else if (id == ASN_COUNTRY_NAME) {
01966                 if (!tooBig) {
01967                     XMEMCPY(&full[idx], "/C=", 3);
01968                     idx += 3;
01969                     copy = TRUE;
01970                 }
01971                 #ifdef CYASSL_CERT_GEN
01972                     if (nameType == SUBJECT) {
01973                         cert->subjectC = (char*)&cert->source[cert->srcIdx];
01974                         cert->subjectCLen = strLen;
01975                         cert->subjectCEnc = b;
01976                     }
01977                 #endif /* CYASSL_CERT_GEN */
01978                 #ifdef OPENSSL_EXTRA
01979                     dName->cIdx = cert->srcIdx;
01980                     dName->cLen = strLen;
01981                 #endif /* OPENSSL_EXTRA */
01982             }
01983             else if (id == ASN_LOCALITY_NAME) {
01984                 if (!tooBig) {
01985                     XMEMCPY(&full[idx], "/L=", 3);
01986                     idx += 3;
01987                     copy = TRUE;
01988                 }
01989                 #ifdef CYASSL_CERT_GEN
01990                     if (nameType == SUBJECT) {
01991                         cert->subjectL = (char*)&cert->source[cert->srcIdx];
01992                         cert->subjectLLen = strLen;
01993                         cert->subjectLEnc = b;
01994                     }
01995                 #endif /* CYASSL_CERT_GEN */
01996                 #ifdef OPENSSL_EXTRA
01997                     dName->lIdx = cert->srcIdx;
01998                     dName->lLen = strLen;
01999                 #endif /* OPENSSL_EXTRA */
02000             }
02001             else if (id == ASN_STATE_NAME) {
02002                 if (!tooBig) {
02003                     XMEMCPY(&full[idx], "/ST=", 4);
02004                     idx += 4;
02005                     copy = TRUE;
02006                 }
02007                 #ifdef CYASSL_CERT_GEN
02008                     if (nameType == SUBJECT) {
02009                         cert->subjectST = (char*)&cert->source[cert->srcIdx];
02010                         cert->subjectSTLen = strLen;
02011                         cert->subjectSTEnc = b;
02012                     }
02013                 #endif /* CYASSL_CERT_GEN */
02014                 #ifdef OPENSSL_EXTRA
02015                     dName->stIdx = cert->srcIdx;
02016                     dName->stLen = strLen;
02017                 #endif /* OPENSSL_EXTRA */
02018             }
02019             else if (id == ASN_ORG_NAME) {
02020                 if (!tooBig) {
02021                     XMEMCPY(&full[idx], "/O=", 3);
02022                     idx += 3;
02023                     copy = TRUE;
02024                 }
02025                 #ifdef CYASSL_CERT_GEN
02026                     if (nameType == SUBJECT) {
02027                         cert->subjectO = (char*)&cert->source[cert->srcIdx];
02028                         cert->subjectOLen = strLen;
02029                         cert->subjectOEnc = b;
02030                     }
02031                 #endif /* CYASSL_CERT_GEN */
02032                 #ifdef OPENSSL_EXTRA
02033                     dName->oIdx = cert->srcIdx;
02034                     dName->oLen = strLen;
02035                 #endif /* OPENSSL_EXTRA */
02036             }
02037             else if (id == ASN_ORGUNIT_NAME) {
02038                 if (!tooBig) {
02039                     XMEMCPY(&full[idx], "/OU=", 4);
02040                     idx += 4;
02041                     copy = TRUE;
02042                 }
02043                 #ifdef CYASSL_CERT_GEN
02044                     if (nameType == SUBJECT) {
02045                         cert->subjectOU = (char*)&cert->source[cert->srcIdx];
02046                         cert->subjectOULen = strLen;
02047                         cert->subjectOUEnc = b;
02048                     }
02049                 #endif /* CYASSL_CERT_GEN */
02050                 #ifdef OPENSSL_EXTRA
02051                     dName->ouIdx = cert->srcIdx;
02052                     dName->ouLen = strLen;
02053                 #endif /* OPENSSL_EXTRA */
02054             }
02055             else if (id == ASN_SERIAL_NUMBER) {
02056                 if (!tooBig) {
02057                    XMEMCPY(&full[idx], "/serialNumber=", 14);
02058                    idx += 14;
02059                    copy = TRUE;
02060                 }
02061                 #ifdef OPENSSL_EXTRA
02062                     dName->snIdx = cert->srcIdx;
02063                     dName->snLen = strLen;
02064                 #endif /* OPENSSL_EXTRA */
02065             }
02066 
02067             if (copy && !tooBig) {
02068                 XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
02069                 idx += strLen;
02070             }
02071 
02072             cert->srcIdx += strLen;
02073         }
02074         else {
02075             /* skip */
02076             byte email = FALSE;
02077             byte uid   = FALSE;
02078             int  adv;
02079 
02080             if (joint[0] == 0x2a && joint[1] == 0x86)  /* email id hdr */
02081                 email = TRUE;
02082 
02083             if (joint[0] == 0x9  && joint[1] == 0x92)  /* uid id hdr */
02084                 uid = TRUE;
02085 
02086             cert->srcIdx += oidSz + 1;
02087 
02088             if (GetLength(cert->source, &cert->srcIdx, &adv, cert->maxIdx) < 0)
02089                 return ASN_PARSE_E;
02090 
02091             if (adv > (int)(ASN_NAME_MAX - idx)) {
02092                 CYASSL_MSG("ASN name too big, skipping");
02093                 tooBig = TRUE;
02094             }
02095 
02096             if (email) {
02097                 if ( (14 + adv) > (int)(ASN_NAME_MAX - idx)) {
02098                     CYASSL_MSG("ASN name too big, skipping");
02099                     tooBig = TRUE;
02100                 }
02101                 if (!tooBig) {
02102                     XMEMCPY(&full[idx], "/emailAddress=", 14);
02103                     idx += 14;
02104                 }
02105 
02106                 #ifdef CYASSL_CERT_GEN
02107                     if (nameType == SUBJECT) {
02108                         cert->subjectEmail = (char*)&cert->source[cert->srcIdx];
02109                         cert->subjectEmailLen = adv;
02110                     }
02111                 #endif /* CYASSL_CERT_GEN */
02112                 #ifdef OPENSSL_EXTRA
02113                     dName->emailIdx = cert->srcIdx;
02114                     dName->emailLen = adv;
02115                 #endif /* OPENSSL_EXTRA */
02116                 #ifndef IGNORE_NAME_CONSTRAINTS
02117                     {
02118                         DNS_entry* emailName = NULL;
02119 
02120                         emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
02121                                               cert->heap, DYNAMIC_TYPE_ALTNAME);
02122                         if (emailName == NULL) {
02123                             CYASSL_MSG("\tOut of Memory");
02124                             return MEMORY_E;
02125                         }
02126                         emailName->name = (char*)XMALLOC(adv + 1,
02127                                               cert->heap, DYNAMIC_TYPE_ALTNAME);
02128                         if (emailName->name == NULL) {
02129                             CYASSL_MSG("\tOut of Memory");
02130                             return MEMORY_E;
02131                         }
02132                         XMEMCPY(emailName->name,
02133                                               &cert->source[cert->srcIdx], adv);
02134                         emailName->name[adv] = 0;
02135 
02136                         emailName->next = cert->altEmailNames;
02137                         cert->altEmailNames = emailName;
02138                     }
02139                 #endif /* IGNORE_NAME_CONSTRAINTS */
02140                 if (!tooBig) {
02141                     XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
02142                     idx += adv;
02143                 }
02144             }
02145 
02146             if (uid) {
02147                 if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) {
02148                     CYASSL_MSG("ASN name too big, skipping");
02149                     tooBig = TRUE;
02150                 }
02151                 if (!tooBig) {
02152                     XMEMCPY(&full[idx], "/UID=", 5);
02153                     idx += 5;
02154 
02155                     XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
02156                     idx += adv;
02157                 }
02158                 #ifdef OPENSSL_EXTRA
02159                     dName->uidIdx = cert->srcIdx;
02160                     dName->uidLen = adv;
02161                 #endif /* OPENSSL_EXTRA */
02162             }
02163 
02164             cert->srcIdx += adv;
02165         }
02166     }
02167     full[idx++] = 0;
02168 
02169     #ifdef OPENSSL_EXTRA
02170     {
02171         int totalLen = 0;
02172 
02173         if (dName->cnLen != 0)
02174             totalLen += dName->cnLen + 4;
02175         if (dName->snLen != 0)
02176             totalLen += dName->snLen + 4;
02177         if (dName->cLen != 0)
02178             totalLen += dName->cLen + 3;
02179         if (dName->lLen != 0)
02180             totalLen += dName->lLen + 3;
02181         if (dName->stLen != 0)
02182             totalLen += dName->stLen + 4;
02183         if (dName->oLen != 0)
02184             totalLen += dName->oLen + 3;
02185         if (dName->ouLen != 0)
02186             totalLen += dName->ouLen + 4;
02187         if (dName->emailLen != 0)
02188             totalLen += dName->emailLen + 14;
02189         if (dName->uidLen != 0)
02190             totalLen += dName->uidLen + 5;
02191         if (dName->serialLen != 0)
02192             totalLen += dName->serialLen + 14;
02193 
02194         dName->fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509);
02195         if (dName->fullName != NULL) {
02196             idx = 0;
02197 
02198             if (dName->cnLen != 0) {
02199                 dName->entryCount++;
02200                 XMEMCPY(&dName->fullName[idx], "/CN=", 4);
02201                 idx += 4;
02202                 XMEMCPY(&dName->fullName[idx],
02203                                      &cert->source[dName->cnIdx], dName->cnLen);
02204                 dName->cnIdx = idx;
02205                 idx += dName->cnLen;
02206             }
02207             if (dName->snLen != 0) {
02208                 dName->entryCount++;
02209                 XMEMCPY(&dName->fullName[idx], "/SN=", 4);
02210                 idx += 4;
02211                 XMEMCPY(&dName->fullName[idx],
02212                                      &cert->source[dName->snIdx], dName->snLen);
02213                 dName->snIdx = idx;
02214                 idx += dName->snLen;
02215             }
02216             if (dName->cLen != 0) {
02217                 dName->entryCount++;
02218                 XMEMCPY(&dName->fullName[idx], "/C=", 3);
02219                 idx += 3;
02220                 XMEMCPY(&dName->fullName[idx],
02221                                        &cert->source[dName->cIdx], dName->cLen);
02222                 dName->cIdx = idx;
02223                 idx += dName->cLen;
02224             }
02225             if (dName->lLen != 0) {
02226                 dName->entryCount++;
02227                 XMEMCPY(&dName->fullName[idx], "/L=", 3);
02228                 idx += 3;
02229                 XMEMCPY(&dName->fullName[idx],
02230                                        &cert->source[dName->lIdx], dName->lLen);
02231                 dName->lIdx = idx;
02232                 idx += dName->lLen;
02233             }
02234             if (dName->stLen != 0) {
02235                 dName->entryCount++;
02236                 XMEMCPY(&dName->fullName[idx], "/ST=", 4);
02237                 idx += 4;
02238                 XMEMCPY(&dName->fullName[idx],
02239                                      &cert->source[dName->stIdx], dName->stLen);
02240                 dName->stIdx = idx;
02241                 idx += dName->stLen;
02242             }
02243             if (dName->oLen != 0) {
02244                 dName->entryCount++;
02245                 XMEMCPY(&dName->fullName[idx], "/O=", 3);
02246                 idx += 3;
02247                 XMEMCPY(&dName->fullName[idx],
02248                                        &cert->source[dName->oIdx], dName->oLen);
02249                 dName->oIdx = idx;
02250                 idx += dName->oLen;
02251             }
02252             if (dName->ouLen != 0) {
02253                 dName->entryCount++;
02254                 XMEMCPY(&dName->fullName[idx], "/OU=", 4);
02255                 idx += 4;
02256                 XMEMCPY(&dName->fullName[idx],
02257                                      &cert->source[dName->ouIdx], dName->ouLen);
02258                 dName->ouIdx = idx;
02259                 idx += dName->ouLen;
02260             }
02261             if (dName->emailLen != 0) {
02262                 dName->entryCount++;
02263                 XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14);
02264                 idx += 14;
02265                 XMEMCPY(&dName->fullName[idx],
02266                                &cert->source[dName->emailIdx], dName->emailLen);
02267                 dName->emailIdx = idx;
02268                 idx += dName->emailLen;
02269             }
02270             if (dName->uidLen != 0) {
02271                 dName->entryCount++;
02272                 XMEMCPY(&dName->fullName[idx], "/UID=", 5);
02273                 idx += 5;
02274                 XMEMCPY(&dName->fullName[idx],
02275                                    &cert->source[dName->uidIdx], dName->uidLen);
02276                 dName->uidIdx = idx;
02277                 idx += dName->uidLen;
02278             }
02279             if (dName->serialLen != 0) {
02280                 dName->entryCount++;
02281                 XMEMCPY(&dName->fullName[idx], "/serialNumber=", 14);
02282                 idx += 14;
02283                 XMEMCPY(&dName->fullName[idx],
02284                              &cert->source[dName->serialIdx], dName->serialLen);
02285                 dName->serialIdx = idx;
02286                 idx += dName->serialLen;
02287             }
02288             dName->fullName[idx] = '\0';
02289             dName->fullNameLen = totalLen;
02290         }
02291     }
02292     #endif /* OPENSSL_EXTRA */
02293 
02294     return 0;
02295 }
02296 
02297 
02298 #ifndef NO_TIME_H
02299 
02300 /* to the second */
02301 static int DateGreaterThan(const struct tm* a, const struct tm* b)
02302 {
02303     if (a->tm_year > b->tm_year)
02304         return 1;
02305 
02306     if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon)
02307         return 1;
02308     
02309     if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
02310            a->tm_mday > b->tm_mday)
02311         return 1;
02312 
02313     if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
02314         a->tm_mday == b->tm_mday && a->tm_hour > b->tm_hour)
02315         return 1;
02316 
02317     if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
02318         a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
02319         a->tm_min > b->tm_min)
02320         return 1;
02321 
02322     if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
02323         a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour &&
02324         a->tm_min  == b->tm_min  && a->tm_sec > b->tm_sec)
02325         return 1;
02326 
02327     return 0; /* false */
02328 }
02329 
02330 
02331 static INLINE int DateLessThan(const struct tm* a, const struct tm* b)
02332 {
02333     return DateGreaterThan(b,a);
02334 }
02335 
02336 
02337 /* like atoi but only use first byte */
02338 /* Make sure before and after dates are valid */
02339 int ValidateDate(const byte* date, byte format, int dateType)
02340 {
02341     time_t ltime;
02342     struct tm  certTime;
02343     struct tm* localTime;
02344     int    i = 0;
02345 
02346     ltime = XTIME(0);
02347     XMEMSET(&certTime, 0, sizeof(certTime));
02348 
02349     if (format == ASN_UTC_TIME) {
02350         if (btoi(date[0]) >= 5)
02351             certTime.tm_year = 1900;
02352         else
02353             certTime.tm_year = 2000;
02354     }
02355     else  { /* format == GENERALIZED_TIME */
02356         certTime.tm_year += btoi(date[i++]) * 1000;
02357         certTime.tm_year += btoi(date[i++]) * 100;
02358     }
02359 
02360     /* adjust tm_year, tm_mon */
02361     GetTime((int*)&certTime.tm_year, date, &i); certTime.tm_year -= 1900;
02362     GetTime((int*)&certTime.tm_mon,  date, &i); certTime.tm_mon  -= 1;
02363     GetTime((int*)&certTime.tm_mday, date, &i);
02364     GetTime((int*)&certTime.tm_hour, date, &i);
02365     GetTime((int*)&certTime.tm_min,  date, &i);
02366     GetTime((int*)&certTime.tm_sec,  date, &i);
02367         
02368         if (date[i] != 'Z') {     /* only Zulu supported for this profile */
02369         CYASSL_MSG("Only Zulu time supported for this profile"); 
02370         return 0;
02371     }
02372 
02373     localTime = XGMTIME(&ltime);
02374 
02375     if (dateType == BEFORE) {
02376         if (DateLessThan(localTime, &certTime))
02377         #ifndef NO_TIME_VERIFY
02378             return 0;
02379         #else
02380             return 1;
02381         #endif
02382     }
02383     else
02384         if (DateGreaterThan(localTime, &certTime))
02385         #ifndef NO_TIME_VERIFY
02386             return 0;
02387         #else
02388             return 1;
02389         #endif
02390 
02391     return 1;
02392 }
02393 
02394 #endif /* NO_TIME_H */
02395 
02396 
02397 static int GetDate(DecodedCert* cert, int dateType)
02398 {
02399     int    length;
02400     byte   date[MAX_DATE_SIZE];
02401     byte   b;
02402     word32 startIdx = 0;
02403 
02404     if (dateType == BEFORE)
02405         cert->beforeDate = &cert->source[cert->srcIdx];
02406     else
02407         cert->afterDate = &cert->source[cert->srcIdx];
02408     startIdx = cert->srcIdx;
02409 
02410     b = cert->source[cert->srcIdx++];
02411     if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME)
02412         return ASN_TIME_E;
02413 
02414     if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
02415         return ASN_PARSE_E;
02416 
02417     if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
02418         return ASN_DATE_SZ_E;
02419 
02420     XMEMCPY(date, &cert->source[cert->srcIdx], length);
02421     cert->srcIdx += length;
02422 
02423     if (dateType == BEFORE)
02424         cert->beforeDateLen = cert->srcIdx - startIdx;
02425     else
02426         cert->afterDateLen  = cert->srcIdx - startIdx;
02427 
02428     if (!XVALIDATE_DATE(date, b, dateType)) {
02429         if (dateType == BEFORE)
02430         #ifdef NO_TIME_VERIFY
02431             return 0;
02432         #else
02433             return ASN_BEFORE_DATE_E;
02434         #endif
02435         else
02436         #ifdef NO_TIME_VERIFY
02437             return 0;
02438         #else
02439             return ASN_AFTER_DATE_E;
02440         #endif
02441     }
02442 
02443     return 0;
02444 }
02445 
02446 
02447 static int GetValidity(DecodedCert* cert, int verify)
02448 {
02449     int length;
02450     int badDate = 0;
02451 
02452     if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
02453         return ASN_PARSE_E;
02454 
02455     if (GetDate(cert, BEFORE) < 0 && verify)
02456         badDate = ASN_BEFORE_DATE_E;           /* continue parsing */
02457     
02458     if (GetDate(cert, AFTER) < 0 && verify)
02459         return ASN_AFTER_DATE_E;
02460    
02461     if (badDate != 0)
02462         return badDate;
02463 
02464     return 0;
02465 }
02466 
02467 
02468 int DecodeToKey(DecodedCert* cert, int verify)
02469 {
02470     int badDate = 0;
02471     int ret;
02472 
02473     if ( (ret = GetCertHeader(cert)) < 0)
02474         return ret;
02475 
02476     CYASSL_MSG("Got Cert Header");
02477 
02478     if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
02479                           cert->maxIdx)) < 0)
02480         return ret;
02481 
02482     CYASSL_MSG("Got Algo ID");
02483 
02484     if ( (ret = GetName(cert, ISSUER)) < 0)
02485         return ret;
02486 
02487     if ( (ret = GetValidity(cert, verify)) < 0)
02488         badDate = ret;
02489 
02490     if ( (ret = GetName(cert, SUBJECT)) < 0)
02491         return ret;
02492 
02493     CYASSL_MSG("Got Subject Name");
02494 
02495     if ( (ret = GetKey(cert)) < 0)
02496         return ret;
02497 
02498     CYASSL_MSG("Got Key");
02499 
02500     if (badDate != 0)
02501         return badDate;
02502 
02503     return ret;
02504 }
02505 
02506 
02507 static int GetSignature(DecodedCert* cert)
02508 {
02509     int    length;
02510     byte   b = cert->source[cert->srcIdx++];
02511 
02512     if (b != ASN_BIT_STRING)
02513         return ASN_BITSTR_E;
02514 
02515     if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
02516         return ASN_PARSE_E;
02517 
02518     cert->sigLength = length;
02519 
02520     b = cert->source[cert->srcIdx++];
02521     if (b != 0x00)
02522         return ASN_EXPECT_0_E;
02523 
02524     cert->sigLength--;
02525     cert->signature = &cert->source[cert->srcIdx];
02526     cert->srcIdx += cert->sigLength;
02527 
02528     return 0;
02529 }
02530 
02531 
02532 static word32 SetDigest(const byte* digest, word32 digSz, byte* output)
02533 {
02534     output[0] = ASN_OCTET_STRING;
02535     output[1] = (byte)digSz;
02536     XMEMCPY(&output[2], digest, digSz);
02537 
02538     return digSz + 2;
02539 } 
02540 
02541 
02542 static word32 BytePrecision(word32 value)
02543 {
02544     word32 i;
02545     for (i = sizeof(value); i; --i)
02546         if (value >> ((i - 1) * CYASSL_BIT_SIZE))
02547             break;
02548 
02549     return i;
02550 }
02551 
02552 
02553 CYASSL_LOCAL word32 SetLength(word32 length, byte* output)
02554 {
02555     word32 i = 0, j;
02556 
02557     if (length < ASN_LONG_LENGTH)
02558         output[i++] = (byte)length;
02559     else {
02560         output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
02561       
02562         for (j = BytePrecision(length); j; --j) {
02563             output[i] = (byte)(length >> ((j - 1) * CYASSL_BIT_SIZE));
02564             i++;
02565         }
02566     }
02567 
02568     return i;
02569 }
02570 
02571 
02572 CYASSL_LOCAL word32 SetSequence(word32 len, byte* output)
02573 {
02574     output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
02575     return SetLength(len, output + 1) + 1;
02576 }
02577 
02578 CYASSL_LOCAL word32 SetOctetString(word32 len, byte* output)
02579 {
02580     output[0] = ASN_OCTET_STRING;
02581     return SetLength(len, output + 1) + 1;
02582 }
02583 
02584 /* Write a set header to output */
02585 CYASSL_LOCAL word32 SetSet(word32 len, byte* output)
02586 {
02587     output[0] = ASN_SET | ASN_CONSTRUCTED;
02588     return SetLength(len, output + 1) + 1;
02589 }
02590 
02591 CYASSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
02592 {
02593 
02594     output[0] = ((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0)
02595                     | ASN_CONTEXT_SPECIFIC | number;
02596     return SetLength(len, output + 1) + 1;
02597 }
02598 
02599 CYASSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output)
02600 {
02601     output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number;
02602     return SetLength(len, output + 1) + 1;
02603 }
02604 
02605 
02606 #if defined(HAVE_ECC) && (defined(CYASSL_CERT_GEN) || defined(CYASSL_KEY_GEN))
02607 
02608 static word32 SetCurve(ecc_key* key, byte* output)
02609 {
02610 
02611     /* curve types */
02612     static const byte ECC_192v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
02613                                              0x03, 0x01, 0x01};
02614     static const byte ECC_256v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
02615                                             0x03, 0x01, 0x07};
02616     static const byte ECC_160r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
02617                                              0x02};
02618     static const byte ECC_224r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
02619                                              0x21};
02620     static const byte ECC_384r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
02621                                              0x22};
02622     static const byte ECC_521r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
02623                                              0x23};
02624 
02625     int    oidSz = 0;
02626     int    idx = 0;
02627     int    lenSz = 0;
02628     const  byte* oid = 0;
02629 
02630     output[0] = ASN_OBJECT_ID;
02631     idx++;
02632 
02633     switch (key->dp->size) {
02634         case 20:
02635             oidSz = sizeof(ECC_160r1_AlgoID);
02636             oid   =        ECC_160r1_AlgoID;
02637             break;
02638 
02639         case 24:
02640             oidSz = sizeof(ECC_192v1_AlgoID);
02641             oid   =        ECC_192v1_AlgoID;
02642             break;
02643 
02644         case 28:
02645             oidSz = sizeof(ECC_224r1_AlgoID);
02646             oid   =        ECC_224r1_AlgoID;
02647             break;
02648 
02649         case 32:
02650             oidSz = sizeof(ECC_256v1_AlgoID);
02651             oid   =        ECC_256v1_AlgoID;
02652             break;
02653 
02654         case 48:
02655             oidSz = sizeof(ECC_384r1_AlgoID);
02656             oid   =        ECC_384r1_AlgoID;
02657             break;
02658 
02659         case 66:
02660             oidSz = sizeof(ECC_521r1_AlgoID);
02661             oid   =        ECC_521r1_AlgoID;
02662             break;
02663 
02664         default:
02665             return ASN_UNKNOWN_OID_E;
02666     }
02667     lenSz = SetLength(oidSz, output+idx);
02668     idx += lenSz;
02669 
02670     XMEMCPY(output+idx, oid, oidSz);
02671     idx += oidSz;
02672 
02673     return idx;
02674 }
02675 
02676 #endif /* HAVE_ECC && CYASSL_CERT_GEN */
02677 
02678 
02679 CYASSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
02680 {
02681     /* adding TAG_NULL and 0 to end */
02682     
02683     /* hashTypes */
02684     static const byte shaAlgoID[]    = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
02685                                          0x05, 0x00 };
02686     static const byte sha256AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
02687                                          0x04, 0x02, 0x01, 0x05, 0x00 };
02688     static const byte sha384AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
02689                                          0x04, 0x02, 0x02, 0x05, 0x00 };
02690     static const byte sha512AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
02691                                          0x04, 0x02, 0x03, 0x05, 0x00 };
02692     static const byte md5AlgoID[]    = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
02693                                          0x02, 0x05, 0x05, 0x00  };
02694     static const byte md2AlgoID[]    = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
02695                                          0x02, 0x02, 0x05, 0x00};
02696 
02697     /* blkTypes, no NULL tags because IV is there instead */
02698     static const byte desCbcAlgoID[]  = { 0x2B, 0x0E, 0x03, 0x02, 0x07 };
02699     static const byte des3CbcAlgoID[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
02700                                           0x0D, 0x03, 0x07 };
02701 
02702     /* RSA sigTypes */
02703     #ifndef NO_RSA
02704         static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
02705                                             0x0d, 0x01, 0x01, 0x04, 0x05, 0x00};
02706         static const byte shawRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
02707                                             0x0d, 0x01, 0x01, 0x05, 0x05, 0x00};
02708         static const byte sha256wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
02709                                             0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00};
02710         static const byte sha384wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
02711                                             0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00};
02712         static const byte sha512wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
02713                                             0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00};
02714     #endif /* NO_RSA */
02715  
02716     /* ECDSA sigTypes */
02717     #ifdef HAVE_ECC 
02718         static const byte shawECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
02719                                                  0x04, 0x01, 0x05, 0x00};
02720         static const byte sha256wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
02721                                                  0x04, 0x03, 0x02, 0x05, 0x00};
02722         static const byte sha384wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
02723                                                  0x04, 0x03, 0x03, 0x05, 0x00};
02724         static const byte sha512wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
02725                                                  0x04, 0x03, 0x04, 0x05, 0x00};
02726     #endif /* HAVE_ECC */
02727  
02728     /* RSA keyType */
02729     #ifndef NO_RSA
02730         static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
02731                                             0x01, 0x01, 0x01, 0x05, 0x00};
02732     #endif /* NO_RSA */
02733 
02734     #ifdef HAVE_ECC 
02735         /* ECC keyType */
02736         /* no tags, so set tagSz smaller later */
02737         static const byte ECC_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
02738                                            0x02, 0x01};
02739     #endif /* HAVE_ECC */
02740 
02741     int    algoSz = 0;
02742     int    tagSz  = 2;   /* tag null and terminator */
02743     word32 idSz, seqSz;
02744     const  byte* algoName = 0;
02745     byte ID_Length[MAX_LENGTH_SZ];
02746     byte seqArray[MAX_SEQ_SZ + 1];  /* add object_id to end */
02747 
02748     if (type == hashType) {
02749         switch (algoOID) {
02750         case SHAh:
02751             algoSz = sizeof(shaAlgoID);
02752             algoName = shaAlgoID;
02753             break;
02754 
02755         case SHA256h:
02756             algoSz = sizeof(sha256AlgoID);
02757             algoName = sha256AlgoID;
02758             break;
02759 
02760         case SHA384h:
02761             algoSz = sizeof(sha384AlgoID);
02762             algoName = sha384AlgoID;
02763             break;
02764 
02765         case SHA512h:
02766             algoSz = sizeof(sha512AlgoID);
02767             algoName = sha512AlgoID;
02768             break;
02769 
02770         case MD2h:
02771             algoSz = sizeof(md2AlgoID);
02772             algoName = md2AlgoID;
02773             break;
02774 
02775         case MD5h:
02776             algoSz = sizeof(md5AlgoID);
02777             algoName = md5AlgoID;
02778             break;
02779 
02780         default:
02781             CYASSL_MSG("Unknown Hash Algo");
02782             return 0;  /* UNKOWN_HASH_E; */
02783         }
02784     }
02785     else if (type == blkType) {
02786         switch (algoOID) {
02787         case DESb:
02788             algoSz = sizeof(desCbcAlgoID);
02789             algoName = desCbcAlgoID;
02790             tagSz = 0;
02791             break;
02792         case DES3b:
02793             algoSz = sizeof(des3CbcAlgoID);
02794             algoName = des3CbcAlgoID;
02795             tagSz = 0;
02796             break;
02797         default:
02798             CYASSL_MSG("Unknown Block Algo");
02799             return 0;
02800         }
02801     }
02802     else if (type == sigType) {    /* sigType */
02803         switch (algoOID) {
02804         #ifndef NO_RSA
02805             case CTC_MD5wRSA:
02806                 algoSz = sizeof(md5wRSA_AlgoID);
02807                 algoName = md5wRSA_AlgoID;
02808                 break;
02809 
02810             case CTC_SHAwRSA:
02811                 algoSz = sizeof(shawRSA_AlgoID);
02812                 algoName = shawRSA_AlgoID;
02813                 break;
02814 
02815             case CTC_SHA256wRSA:
02816                 algoSz = sizeof(sha256wRSA_AlgoID);
02817                 algoName = sha256wRSA_AlgoID;
02818                 break;
02819 
02820             case CTC_SHA384wRSA:
02821                 algoSz = sizeof(sha384wRSA_AlgoID);
02822                 algoName = sha384wRSA_AlgoID;
02823                 break;
02824 
02825             case CTC_SHA512wRSA:
02826                 algoSz = sizeof(sha512wRSA_AlgoID);
02827                 algoName = sha512wRSA_AlgoID;
02828                 break;
02829         #endif /* NO_RSA */
02830         #ifdef HAVE_ECC 
02831             case CTC_SHAwECDSA:
02832                 algoSz = sizeof(shawECDSA_AlgoID);
02833                 algoName = shawECDSA_AlgoID;
02834                 break;
02835 
02836             case CTC_SHA256wECDSA:
02837                 algoSz = sizeof(sha256wECDSA_AlgoID);
02838                 algoName = sha256wECDSA_AlgoID;
02839                 break;
02840 
02841             case CTC_SHA384wECDSA:
02842                 algoSz = sizeof(sha384wECDSA_AlgoID);
02843                 algoName = sha384wECDSA_AlgoID;
02844                 break;
02845 
02846             case CTC_SHA512wECDSA:
02847                 algoSz = sizeof(sha512wECDSA_AlgoID);
02848                 algoName = sha512wECDSA_AlgoID;
02849                 break;
02850         #endif /* HAVE_ECC */
02851         default:
02852             CYASSL_MSG("Unknown Signature Algo");
02853             return 0;
02854         }
02855     }
02856     else if (type == keyType) {    /* keyType */
02857         switch (algoOID) {
02858         #ifndef NO_RSA
02859             case RSAk:
02860                 algoSz = sizeof(RSA_AlgoID);
02861                 algoName = RSA_AlgoID;
02862                 break;
02863         #endif /* NO_RSA */
02864         #ifdef HAVE_ECC 
02865             case ECDSAk:
02866                 algoSz = sizeof(ECC_AlgoID);
02867                 algoName = ECC_AlgoID;
02868                 tagSz = 0;
02869                 break;
02870         #endif /* HAVE_ECC */
02871         default:
02872             CYASSL_MSG("Unknown Key Algo");
02873             return 0;
02874         }
02875     }
02876     else {
02877         CYASSL_MSG("Unknown Algo type");
02878         return 0;
02879     }
02880 
02881     idSz  = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */
02882     seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray); 
02883                  /* +1 for object id, curveID of curveSz follows for ecc */
02884     seqArray[seqSz++] = ASN_OBJECT_ID;
02885 
02886     XMEMCPY(output, seqArray, seqSz);
02887     XMEMCPY(output + seqSz, ID_Length, idSz);
02888     XMEMCPY(output + seqSz + idSz, algoName, algoSz);
02889 
02890     return seqSz + idSz + algoSz;
02891 
02892 }
02893 
02894 
02895 word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID)
02896 {
02897     byte digArray[MAX_ENCODED_DIG_SZ];
02898     byte algoArray[MAX_ALGO_SZ];
02899     byte seqArray[MAX_SEQ_SZ];
02900     word32 encDigSz, algoSz, seqSz; 
02901 
02902     encDigSz = SetDigest(digest, digSz, digArray);
02903     algoSz   = SetAlgoID(hashOID, algoArray, hashType, 0);
02904     seqSz    = SetSequence(encDigSz + algoSz, seqArray);
02905 
02906     XMEMCPY(out, seqArray, seqSz);
02907     XMEMCPY(out + seqSz, algoArray, algoSz);
02908     XMEMCPY(out + seqSz + algoSz, digArray, encDigSz);
02909 
02910     return encDigSz + algoSz + seqSz;
02911 }
02912 
02913 
02914 int GetCTC_HashOID(int type)
02915 {
02916     switch (type) {
02917 #ifdef CYASSL_MD2
02918         case MD2:
02919             return MD2h;
02920 #endif
02921 #ifndef NO_MD5
02922         case MD5:
02923             return MD5h;
02924 #endif
02925 #ifndef NO_SHA
02926         case SHA:
02927             return SHAh;
02928 #endif
02929 #ifndef NO_SHA256
02930         case SHA256:
02931             return SHA256h;
02932 #endif
02933 #ifdef CYASSL_SHA384
02934         case SHA384:
02935             return SHA384h;
02936 #endif
02937 #ifdef CYASSL_SHA512
02938         case SHA512:
02939             return SHA512h;
02940 #endif
02941         default:
02942             return 0;
02943     };
02944 }
02945 
02946 
02947 /* return true (1) or false (0) for Confirmation */
02948 static int ConfirmSignature(const byte* buf, word32 bufSz,
02949     const byte* key, word32 keySz, word32 keyOID,
02950     const byte* sig, word32 sigSz, word32 sigOID,
02951     void* heap)
02952 {
02953     int  typeH = 0, digestSz = 0, ret = 0;
02954 #ifdef CYASSL_SMALL_STACK
02955     byte* digest;
02956 #else
02957     byte digest[MAX_DIGEST_SIZE];
02958 #endif
02959 
02960 #ifdef CYASSL_SMALL_STACK
02961     digest = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
02962     if (digest == NULL)
02963         return 0; /* not confirmed */
02964 #endif
02965 
02966     (void)key;
02967     (void)keySz;
02968     (void)sig;
02969     (void)sigSz;
02970     (void)heap;
02971 
02972     switch (sigOID) {
02973     #ifndef NO_MD5
02974         case CTC_MD5wRSA:
02975         if (Md5Hash(buf, bufSz, digest) == 0) {
02976             typeH    = MD5h;
02977             digestSz = MD5_DIGEST_SIZE;
02978         }
02979         break;
02980     #endif
02981     #if defined(CYASSL_MD2)
02982         case CTC_MD2wRSA:
02983         if (Md2Hash(buf, bufSz, digest) == 0) {
02984             typeH    = MD2h;
02985             digestSz = MD2_DIGEST_SIZE;
02986         }
02987         break;
02988     #endif
02989     #ifndef NO_SHA
02990         case CTC_SHAwRSA:
02991         case CTC_SHAwDSA:
02992         case CTC_SHAwECDSA:
02993         if (ShaHash(buf, bufSz, digest) == 0) {    
02994             typeH    = SHAh;
02995             digestSz = SHA_DIGEST_SIZE;                
02996         }
02997         break;
02998     #endif
02999     #ifndef NO_SHA256
03000         case CTC_SHA256wRSA:
03001         case CTC_SHA256wECDSA:
03002         if (Sha256Hash(buf, bufSz, digest) == 0) {    
03003             typeH    = SHA256h;
03004             digestSz = SHA256_DIGEST_SIZE;
03005         }
03006         break;
03007     #endif
03008     #ifdef CYASSL_SHA512
03009         case CTC_SHA512wRSA:
03010         case CTC_SHA512wECDSA:
03011         if (Sha512Hash(buf, bufSz, digest) == 0) {    
03012             typeH    = SHA512h;
03013             digestSz = SHA512_DIGEST_SIZE;
03014         }
03015         break;
03016     #endif
03017     #ifdef CYASSL_SHA384
03018         case CTC_SHA384wRSA:
03019         case CTC_SHA384wECDSA:
03020         if (Sha384Hash(buf, bufSz, digest) == 0) {    
03021             typeH    = SHA384h;
03022             digestSz = SHA384_DIGEST_SIZE;
03023         }            
03024         break;
03025     #endif
03026         default:
03027             CYASSL_MSG("Verify Signautre has unsupported type");
03028     }
03029     
03030     if (typeH == 0) {
03031 #ifdef CYASSL_SMALL_STACK
03032         XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03033 #endif
03034         return 0; /* not confirmed */
03035     }
03036 
03037     switch (keyOID) {
03038     #ifndef NO_RSA
03039         case RSAk:
03040         {
03041             word32 idx = 0;
03042             int    encodedSigSz, verifySz;
03043             byte*  out;
03044 #ifdef CYASSL_SMALL_STACK
03045             RsaKey* pubKey;
03046             byte* plain;
03047             byte* encodedSig;
03048 #else
03049             RsaKey pubKey[1];
03050             byte plain[MAX_ENCODED_SIG_SZ];
03051             byte encodedSig[MAX_ENCODED_SIG_SZ];
03052 #endif
03053 
03054 #ifdef CYASSL_SMALL_STACK
03055             pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
03056                                                        DYNAMIC_TYPE_TMP_BUFFER);
03057             plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
03058                                                        DYNAMIC_TYPE_TMP_BUFFER);
03059             encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
03060                                                        DYNAMIC_TYPE_TMP_BUFFER);
03061             
03062             if (pubKey == NULL || plain == NULL || encodedSig == NULL) {
03063                 CYASSL_MSG("Failed to allocate memory at ConfirmSignature");
03064                 
03065                 if (pubKey)
03066                     XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03067                 if (plain)
03068                     XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03069                 if (encodedSig)
03070                     XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03071                 
03072                 break; /* not confirmed */
03073             }
03074 #endif
03075 
03076             if (sigSz > MAX_ENCODED_SIG_SZ) {
03077                 CYASSL_MSG("Verify Signautre is too big");
03078             }
03079             else if (InitRsaKey(pubKey, heap) != 0) {
03080                 CYASSL_MSG("InitRsaKey failed");
03081             }
03082             else if (RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) {
03083                 CYASSL_MSG("ASN Key decode error RSA");
03084             }
03085             else {
03086                 XMEMCPY(plain, sig, sigSz);
03087 
03088                 if ((verifySz = RsaSSL_VerifyInline(plain, sigSz, &out,
03089                                                                  pubKey)) < 0) {
03090                     CYASSL_MSG("Rsa SSL verify error");
03091                 }
03092                 else {
03093                     /* make sure we're right justified */
03094                     encodedSigSz =
03095                         EncodeSignature(encodedSig, digest, digestSz, typeH);
03096                     if (encodedSigSz != verifySz ||
03097                                 XMEMCMP(out, encodedSig, encodedSigSz) != 0) {
03098                         CYASSL_MSG("Rsa SSL verify match encode error");
03099                     }
03100                     else
03101                         ret = 1; /* match */
03102 
03103                     #ifdef CYASSL_DEBUG_ENCODING
03104                     {
03105                         int x;
03106                         
03107                         printf("cyassl encodedSig:\n");
03108                         
03109                         for (x = 0; x < encodedSigSz; x++) {
03110                             printf("%02x ", encodedSig[x]);
03111                             if ( (x % 16) == 15)
03112                                 printf("\n");
03113                         }
03114                         
03115                         printf("\n");
03116                         printf("actual digest:\n");
03117                         
03118                         for (x = 0; x < verifySz; x++) {
03119                             printf("%02x ", out[x]);
03120                             if ( (x % 16) == 15)
03121                                 printf("\n");
03122                         }
03123                         
03124                         printf("\n");
03125                     }
03126                     #endif /* CYASSL_DEBUG_ENCODING */
03127                     
03128                 }
03129                 
03130             }
03131             
03132             FreeRsaKey(pubKey);
03133             
03134 #ifdef CYASSL_SMALL_STACK
03135             XFREE(pubKey,     NULL, DYNAMIC_TYPE_TMP_BUFFER);
03136             XFREE(plain,      NULL, DYNAMIC_TYPE_TMP_BUFFER);
03137             XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03138 #endif
03139             break;
03140         }
03141 
03142     #endif /* NO_RSA */
03143     #ifdef HAVE_ECC
03144         case ECDSAk:
03145         {
03146             int verify = 0;
03147 #ifdef CYASSL_SMALL_STACK
03148             ecc_key* pubKey;
03149 #else
03150             ecc_key pubKey[1];
03151 #endif
03152 
03153 #ifdef CYASSL_SMALL_STACK
03154             pubKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
03155                                                        DYNAMIC_TYPE_TMP_BUFFER);
03156             if (pubKey == NULL) {
03157                 CYASSL_MSG("Failed to allocate pubKey");
03158                 break; /* not confirmed */
03159             }
03160 #endif
03161 
03162             if (ecc_import_x963(key, keySz, pubKey) < 0) {
03163                 CYASSL_MSG("ASN Key import error ECC");
03164             }
03165             else {   
03166                 if (ecc_verify_hash(sig, sigSz, digest, digestSz, &verify,
03167                                                                 pubKey) != 0) {
03168                     CYASSL_MSG("ECC verify hash error");
03169                 }
03170                 else if (1 != verify) {
03171                     CYASSL_MSG("ECC Verify didn't match");
03172                 } else
03173                     ret = 1; /* match */
03174 
03175                 ecc_free(pubKey);
03176             }
03177 #ifdef CYASSL_SMALL_STACK
03178             XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03179 #endif
03180             break;
03181         }
03182     #endif /* HAVE_ECC */
03183         default:
03184             CYASSL_MSG("Verify Key type unknown");
03185     }
03186     
03187 #ifdef CYASSL_SMALL_STACK
03188     XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03189 #endif
03190 
03191     return ret;
03192 }
03193 
03194 
03195 #ifndef IGNORE_NAME_CONSTRAINTS
03196 
03197 static int MatchBaseName(int type, const char* name, int nameSz,
03198                                                    const char* base, int baseSz)
03199 {
03200     if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 ||
03201             name[0] == '.' || nameSz < baseSz ||
03202             (type != ASN_RFC822_TYPE && type != ASN_DNS_TYPE))
03203         return 0;
03204 
03205     /* If an email type, handle special cases where the base is only
03206      * a domain, or is an email address itself. */
03207     if (type == ASN_RFC822_TYPE) {
03208         const char* p = NULL;
03209         int count = 0;
03210 
03211         if (base[0] != '.') {
03212             p = base;
03213             count = 0;
03214 
03215             /* find the '@' in the base */
03216             while (*p != '@' && count < baseSz) {
03217                 count++;
03218                 p++;
03219             }
03220 
03221             /* No '@' in base, reset p to NULL */
03222             if (count >= baseSz)
03223                 p = NULL;
03224         }
03225 
03226         if (p == NULL) {
03227             /* Base isn't an email address, it is a domain name,
03228              * wind the name forward one character past its '@'. */
03229             p = name;
03230             count = 0;
03231             while (*p != '@' && count < baseSz) {
03232                 count++;
03233                 p++;
03234             }
03235 
03236             if (count < baseSz && *p == '@') {
03237                 name = p + 1;
03238                 nameSz -= count + 1;
03239             }
03240         }
03241     }
03242 
03243     if ((type == ASN_DNS_TYPE || type == ASN_RFC822_TYPE) && base[0] == '.') {
03244         int szAdjust = nameSz - baseSz;
03245         name += szAdjust;
03246         nameSz -= szAdjust;
03247     }
03248 
03249     while (nameSz > 0) {
03250         if (XTOLOWER(*name++) != XTOLOWER(*base++))
03251             return 0;
03252         nameSz--;
03253     }
03254 
03255     return 1;
03256 }
03257 
03258 
03259 static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
03260 {
03261     if (signer == NULL || cert == NULL)
03262         return 0;
03263 
03264     /* Check against the excluded list */
03265     if (signer->excludedNames) {
03266         Base_entry* base = signer->excludedNames;
03267 
03268         while (base != NULL) {
03269             if (base->type == ASN_DNS_TYPE) {
03270                 DNS_entry* name = cert->altNames;
03271                 while (name != NULL) {
03272                     if (MatchBaseName(ASN_DNS_TYPE,
03273                                           name->name, (int)XSTRLEN(name->name),
03274                                           base->name, base->nameSz))
03275                         return 0;
03276                     name = name->next;
03277                 }
03278             }
03279             else if (base->type == ASN_RFC822_TYPE) {
03280                 DNS_entry* name = cert->altEmailNames;
03281                 while (name != NULL) {
03282                     if (MatchBaseName(ASN_RFC822_TYPE,
03283                                           name->name, (int)XSTRLEN(name->name),
03284                                           base->name, base->nameSz))
03285                         return 0;
03286 
03287                     name = name->next;
03288                 }
03289             }
03290             else if (base->type == ASN_DIR_TYPE) {
03291                 if (cert->subjectRawLen == base->nameSz &&
03292                     XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
03293 
03294                     return 0;
03295                 }
03296             }
03297             base = base->next;
03298         }
03299     }
03300 
03301     /* Check against the permitted list */
03302     if (signer->permittedNames != NULL) {
03303         int needDns = 0;
03304         int matchDns = 0;
03305         int needEmail = 0;
03306         int matchEmail = 0;
03307         int needDir = 0;
03308         int matchDir = 0;
03309         Base_entry* base = signer->permittedNames;
03310 
03311         while (base != NULL) {
03312             if (base->type == ASN_DNS_TYPE) {
03313                 DNS_entry* name = cert->altNames;
03314 
03315                 if (name != NULL)
03316                     needDns = 1;
03317 
03318                 while (name != NULL) {
03319                     matchDns = MatchBaseName(ASN_DNS_TYPE,
03320                                           name->name, (int)XSTRLEN(name->name),
03321                                           base->name, base->nameSz);
03322                     name = name->next;
03323                 }
03324             }
03325             else if (base->type == ASN_RFC822_TYPE) {
03326                 DNS_entry* name = cert->altEmailNames;
03327 
03328                 if (name != NULL)
03329                     needEmail = 1;
03330 
03331                 while (name != NULL) {
03332                     matchEmail = MatchBaseName(ASN_DNS_TYPE,
03333                                           name->name, (int)XSTRLEN(name->name),
03334                                           base->name, base->nameSz);
03335                     name = name->next;
03336                 }
03337             }
03338             else if (base->type == ASN_DIR_TYPE) {
03339                 needDir = 1;
03340                 if (cert->subjectRaw != NULL &&
03341                     cert->subjectRawLen == base->nameSz &&
03342                     XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
03343 
03344                     matchDir = 1;
03345                 }
03346             }
03347             base = base->next;
03348         }
03349 
03350         if ((needDns && !matchDns) || (needEmail && !matchEmail) ||
03351             (needDir && !matchDir)) {
03352 
03353             return 0;
03354         }
03355     }
03356 
03357     return 1;
03358 }
03359 
03360 #endif /* IGNORE_NAME_CONSTRAINTS */
03361 
03362 
03363 static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
03364 {
03365     word32 idx = 0;
03366     int length = 0;
03367 
03368     CYASSL_ENTER("DecodeAltNames");
03369 
03370     if (GetSequence(input, &idx, &length, sz) < 0) {
03371         CYASSL_MSG("\tBad Sequence");
03372         return ASN_PARSE_E;
03373     }
03374 
03375     while (length > 0) {
03376         byte       b = input[idx++];
03377 
03378         length--;
03379 
03380         /* Save DNS Type names in the altNames list. */
03381         /* Save Other Type names in the cert's OidMap */
03382         if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE)) {
03383             DNS_entry* dnsEntry;
03384             int strLen;
03385             word32 lenStartIdx = idx;
03386 
03387             if (GetLength(input, &idx, &strLen, sz) < 0) {
03388                 CYASSL_MSG("\tfail: str length");
03389                 return ASN_PARSE_E;
03390             }
03391             length -= (idx - lenStartIdx);
03392 
03393             dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
03394                                         DYNAMIC_TYPE_ALTNAME);
03395             if (dnsEntry == NULL) {
03396                 CYASSL_MSG("\tOut of Memory");
03397                 return ASN_PARSE_E;
03398             }
03399 
03400             dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
03401                                          DYNAMIC_TYPE_ALTNAME);
03402             if (dnsEntry->name == NULL) {
03403                 CYASSL_MSG("\tOut of Memory");
03404                 XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
03405                 return ASN_PARSE_E;
03406             }
03407 
03408             XMEMCPY(dnsEntry->name, &input[idx], strLen);
03409             dnsEntry->name[strLen] = '\0';
03410 
03411             dnsEntry->next = cert->altNames;
03412             cert->altNames = dnsEntry;
03413 
03414             length -= strLen;
03415             idx    += strLen;
03416         }
03417 #ifndef IGNORE_NAME_CONSTRAINTS
03418         else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
03419             DNS_entry* emailEntry;
03420             int strLen;
03421             word32 lenStartIdx = idx;
03422 
03423             if (GetLength(input, &idx, &strLen, sz) < 0) {
03424                 CYASSL_MSG("\tfail: str length");
03425                 return ASN_PARSE_E;
03426             }
03427             length -= (idx - lenStartIdx);
03428 
03429             emailEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
03430                                         DYNAMIC_TYPE_ALTNAME);
03431             if (emailEntry == NULL) {
03432                 CYASSL_MSG("\tOut of Memory");
03433                 return ASN_PARSE_E;
03434             }
03435 
03436             emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
03437                                          DYNAMIC_TYPE_ALTNAME);
03438             if (emailEntry->name == NULL) {
03439                 CYASSL_MSG("\tOut of Memory");
03440                 XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
03441                 return ASN_PARSE_E;
03442             }
03443 
03444             XMEMCPY(emailEntry->name, &input[idx], strLen);
03445             emailEntry->name[strLen] = '\0';
03446 
03447             emailEntry->next = cert->altEmailNames;
03448             cert->altEmailNames = emailEntry;
03449 
03450             length -= strLen;
03451             idx    += strLen;
03452         }
03453 #endif /* IGNORE_NAME_CONSTRAINTS */
03454 #ifdef CYASSL_SEP
03455         else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE))
03456         {
03457             int strLen;
03458             word32 lenStartIdx = idx;
03459             word32 oid = 0;
03460 
03461             if (GetLength(input, &idx, &strLen, sz) < 0) {
03462                 CYASSL_MSG("\tfail: other name length");
03463                 return ASN_PARSE_E;
03464             }
03465             /* Consume the rest of this sequence. */
03466             length -= (strLen + idx - lenStartIdx);
03467 
03468             if (GetObjectId(input, &idx, &oid, sz) < 0) {
03469                 CYASSL_MSG("\tbad OID");
03470                 return ASN_PARSE_E;
03471             }
03472 
03473             if (oid != HW_NAME_OID) {
03474                 CYASSL_MSG("\tincorrect OID");
03475                 return ASN_PARSE_E;
03476             }
03477 
03478             if (input[idx++] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
03479                 CYASSL_MSG("\twrong type");
03480                 return ASN_PARSE_E;
03481             }
03482 
03483             if (GetLength(input, &idx, &strLen, sz) < 0) {
03484                 CYASSL_MSG("\tfail: str len");
03485                 return ASN_PARSE_E;
03486             }
03487 
03488             if (GetSequence(input, &idx, &strLen, sz) < 0) {
03489                 CYASSL_MSG("\tBad Sequence");
03490                 return ASN_PARSE_E;
03491             }
03492 
03493             if (input[idx++] != ASN_OBJECT_ID) {
03494                 CYASSL_MSG("\texpected OID");
03495                 return ASN_PARSE_E;
03496             }
03497 
03498             if (GetLength(input, &idx, &strLen, sz) < 0) {
03499                 CYASSL_MSG("\tfailed: str len");
03500                 return ASN_PARSE_E;
03501             }
03502 
03503             cert->hwType = (byte*)XMALLOC(strLen, cert->heap, 0);
03504             if (cert->hwType == NULL) {
03505                 CYASSL_MSG("\tOut of Memory");
03506                 return MEMORY_E;
03507             }
03508 
03509             XMEMCPY(cert->hwType, &input[idx], strLen);
03510             cert->hwTypeSz = strLen;
03511             idx += strLen;
03512 
03513             if (input[idx++] != ASN_OCTET_STRING) {
03514                 CYASSL_MSG("\texpected Octet String");
03515                 return ASN_PARSE_E;
03516             }
03517 
03518             if (GetLength(input, &idx, &strLen, sz) < 0) {
03519                 CYASSL_MSG("\tfailed: str len");
03520                 return ASN_PARSE_E;
03521             }
03522 
03523             cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, 0);
03524             if (cert->hwSerialNum == NULL) {
03525                 CYASSL_MSG("\tOut of Memory");
03526                 return MEMORY_E;
03527             }
03528 
03529             XMEMCPY(cert->hwSerialNum, &input[idx], strLen);
03530             cert->hwSerialNum[strLen] = '\0';
03531             cert->hwSerialNumSz = strLen;
03532             idx += strLen;
03533         }
03534 #endif /* CYASSL_SEP */
03535         else {
03536             int strLen;
03537             word32 lenStartIdx = idx;
03538 
03539             CYASSL_MSG("\tUnsupported name type, skipping");
03540 
03541             if (GetLength(input, &idx, &strLen, sz) < 0) {
03542                 CYASSL_MSG("\tfail: unsupported name length");
03543                 return ASN_PARSE_E;
03544             }
03545             length -= (strLen + idx - lenStartIdx);
03546             idx += strLen;
03547         }
03548     }
03549     return 0;
03550 }
03551 
03552 
03553 static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
03554 {
03555     word32 idx = 0;
03556     int length = 0;
03557 
03558     CYASSL_ENTER("DecodeBasicCaConstraint");
03559     if (GetSequence(input, &idx, &length, sz) < 0) {
03560         CYASSL_MSG("\tfail: bad SEQUENCE");
03561         return ASN_PARSE_E;
03562     }
03563 
03564     if (length == 0)
03565         return 0;
03566 
03567     /* If the basic ca constraint is false, this extension may be named, but
03568      * left empty. So, if the length is 0, just return. */
03569 
03570     if (input[idx++] != ASN_BOOLEAN)
03571     {
03572         CYASSL_MSG("\tfail: constraint not BOOLEAN");
03573         return ASN_PARSE_E;
03574     }
03575 
03576     if (GetLength(input, &idx, &length, sz) < 0)
03577     {
03578         CYASSL_MSG("\tfail: length");
03579         return ASN_PARSE_E;
03580     }
03581 
03582     if (input[idx++])
03583         cert->isCA = 1;
03584 
03585     #ifdef OPENSSL_EXTRA
03586         /* If there isn't any more data, return. */
03587         if (idx >= (word32)sz)
03588             return 0;
03589 
03590         /* Anything left should be the optional pathlength */
03591         if (input[idx++] != ASN_INTEGER) {
03592             CYASSL_MSG("\tfail: pathlen not INTEGER");
03593             return ASN_PARSE_E;
03594         }
03595 
03596         if (input[idx++] != 1) {
03597             CYASSL_MSG("\tfail: pathlen too long");
03598             return ASN_PARSE_E;
03599         }
03600 
03601         cert->pathLength = input[idx];
03602         cert->extBasicConstPlSet = 1;
03603     #endif /* OPENSSL_EXTRA */
03604 
03605     return 0;
03606 }
03607 
03608 
03609 #define CRLDP_FULL_NAME 0
03610     /* From RFC3280 SS4.2.1.14, Distribution Point Name*/
03611 #define GENERALNAME_URI 6
03612     /* From RFC3280 SS4.2.1.7, GeneralName */
03613 
03614 static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
03615 {
03616     word32 idx = 0;
03617     int length = 0;
03618 
03619     CYASSL_ENTER("DecodeCrlDist");
03620 
03621     /* Unwrap the list of Distribution Points*/
03622     if (GetSequence(input, &idx, &length, sz) < 0)
03623         return ASN_PARSE_E;
03624 
03625     /* Unwrap a single Distribution Point */
03626     if (GetSequence(input, &idx, &length, sz) < 0)
03627         return ASN_PARSE_E;
03628 
03629     /* The Distribution Point has three explicit optional members
03630      *  First check for a DistributionPointName
03631      */
03632     if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
03633     {
03634         idx++;
03635         if (GetLength(input, &idx, &length, sz) < 0)
03636             return ASN_PARSE_E;
03637 
03638         if (input[idx] == 
03639                     (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME))
03640         {
03641             idx++;
03642             if (GetLength(input, &idx, &length, sz) < 0)
03643                 return ASN_PARSE_E;
03644 
03645             if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
03646             {
03647                 idx++;
03648                 if (GetLength(input, &idx, &length, sz) < 0)
03649                     return ASN_PARSE_E;
03650 
03651                 cert->extCrlInfoSz = length;
03652                 cert->extCrlInfo = input + idx;
03653                 idx += length;
03654             }
03655             else
03656                 /* This isn't a URI, skip it. */
03657                 idx += length;
03658         }
03659         else
03660             /* This isn't a FULLNAME, skip it. */
03661             idx += length;
03662     }
03663 
03664     /* Check for reasonFlags */
03665     if (idx < (word32)sz &&
03666         input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
03667     {
03668         idx++;
03669         if (GetLength(input, &idx, &length, sz) < 0)
03670             return ASN_PARSE_E;
03671         idx += length;
03672     }
03673 
03674     /* Check for cRLIssuer */
03675     if (idx < (word32)sz &&
03676         input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
03677     {
03678         idx++;
03679         if (GetLength(input, &idx, &length, sz) < 0)
03680             return ASN_PARSE_E;
03681         idx += length;
03682     }
03683 
03684     if (idx < (word32)sz)
03685     {
03686         CYASSL_MSG("\tThere are more CRL Distribution Point records, "
03687                    "but we only use the first one.");
03688     }
03689 
03690     return 0;
03691 }
03692 
03693 
03694 static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
03695 /*
03696  *  Read the first of the Authority Information Access records. If there are
03697  *  any issues, return without saving the record.
03698  */
03699 {
03700     word32 idx = 0;
03701     int length = 0;
03702     byte b;
03703     word32 oid;
03704 
03705     CYASSL_ENTER("DecodeAuthInfo");
03706 
03707     /* Unwrap the list of AIAs */
03708     if (GetSequence(input, &idx, &length, sz) < 0)
03709         return ASN_PARSE_E;
03710 
03711     while (idx < (word32)sz) {
03712         /* Unwrap a single AIA */
03713         if (GetSequence(input, &idx, &length, sz) < 0)
03714             return ASN_PARSE_E;
03715 
03716         oid = 0;
03717         if (GetObjectId(input, &idx, &oid, sz) < 0)
03718             return ASN_PARSE_E;
03719 
03720         /* Only supporting URIs right now. */
03721         b = input[idx++];
03722         if (GetLength(input, &idx, &length, sz) < 0)
03723             return ASN_PARSE_E;
03724 
03725         if (b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI) &&
03726             oid == AIA_OCSP_OID)
03727         {
03728             cert->extAuthInfoSz = length;
03729             cert->extAuthInfo = input + idx;
03730             break;
03731         }
03732         idx += length;
03733     }
03734 
03735     return 0;
03736 }
03737 
03738 
03739 static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
03740 {
03741     word32 idx = 0;
03742     int length = 0, ret = 0;
03743 
03744     CYASSL_ENTER("DecodeAuthKeyId");
03745 
03746     if (GetSequence(input, &idx, &length, sz) < 0) {
03747         CYASSL_MSG("\tfail: should be a SEQUENCE\n");
03748         return ASN_PARSE_E;
03749     }
03750 
03751     if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
03752         CYASSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
03753         return 0;
03754     }
03755 
03756     if (GetLength(input, &idx, &length, sz) < 0) {
03757         CYASSL_MSG("\tfail: extension data length");
03758         return ASN_PARSE_E;
03759     }
03760 
03761     #ifdef OPENSSL_EXTRA
03762         cert->extAuthKeyIdSrc = &input[idx];
03763         cert->extAuthKeyIdSz = length;
03764     #endif /* OPENSSL_EXTRA */
03765 
03766     if (length == SHA_SIZE) {
03767         XMEMCPY(cert->extAuthKeyId, input + idx, length);
03768     }
03769     else {
03770         Sha sha;
03771         ret = InitSha(&sha);
03772         if (ret != 0)
03773             return ret;
03774         ShaUpdate(&sha, input + idx, length);
03775         ShaFinal(&sha, cert->extAuthKeyId);
03776     }
03777 
03778     return 0;
03779 }
03780 
03781 
03782 static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert)
03783 {
03784     word32 idx = 0;
03785     int length = 0, ret = 0;
03786 
03787     CYASSL_ENTER("DecodeSubjKeyId");
03788 
03789     if (input[idx++] != ASN_OCTET_STRING) {
03790         CYASSL_MSG("\tfail: should be an OCTET STRING");
03791         return ASN_PARSE_E;
03792     }
03793 
03794     if (GetLength(input, &idx, &length, sz) < 0) {
03795         CYASSL_MSG("\tfail: extension data length");
03796         return ASN_PARSE_E;
03797     }
03798 
03799     #ifdef OPENSSL_EXTRA
03800         cert->extSubjKeyIdSrc = &input[idx];
03801         cert->extSubjKeyIdSz = length;
03802     #endif /* OPENSSL_EXTRA */
03803 
03804     if (length == SIGNER_DIGEST_SIZE) {
03805         XMEMCPY(cert->extSubjKeyId, input + idx, length);
03806     }
03807     else {
03808         Sha sha;
03809         ret = InitSha(&sha);
03810         if (ret != 0)
03811             return ret;
03812         ShaUpdate(&sha, input + idx, length);
03813         ShaFinal(&sha, cert->extSubjKeyId);
03814     }
03815 
03816     return ret;
03817 }
03818 
03819 
03820 static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert)
03821 {
03822     word32 idx = 0;
03823     int length;
03824     byte unusedBits;
03825     CYASSL_ENTER("DecodeKeyUsage");
03826 
03827     if (input[idx++] != ASN_BIT_STRING) {
03828         CYASSL_MSG("\tfail: key usage expected bit string");
03829         return ASN_PARSE_E;
03830     }
03831 
03832     if (GetLength(input, &idx, &length, sz) < 0) {
03833         CYASSL_MSG("\tfail: key usage bad length");
03834         return ASN_PARSE_E;
03835     }
03836 
03837     unusedBits = input[idx++];
03838     length--;
03839 
03840     if (length == 2) {
03841         cert->extKeyUsage = (word16)((input[idx] << 8) | input[idx+1]);
03842         cert->extKeyUsage >>= unusedBits;
03843     }
03844     else if (length == 1)
03845         cert->extKeyUsage = (word16)(input[idx] << 1);
03846 
03847     return 0;
03848 }
03849 
03850 
03851 static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
03852 {
03853     word32 idx = 0, oid;
03854     int length;
03855 
03856     CYASSL_ENTER("DecodeExtKeyUsage");
03857 
03858     if (GetSequence(input, &idx, &length, sz) < 0) {
03859         CYASSL_MSG("\tfail: should be a SEQUENCE");
03860         return ASN_PARSE_E;
03861     }
03862 
03863     #ifdef OPENSSL_EXTRA
03864         cert->extExtKeyUsageSrc = input + idx;
03865         cert->extExtKeyUsageSz = length;
03866     #endif
03867 
03868     while (idx < (word32)sz) {
03869         if (GetObjectId(input, &idx, &oid, sz) < 0)
03870             return ASN_PARSE_E;
03871 
03872         switch (oid) {
03873             case EKU_ANY_OID:
03874                 cert->extExtKeyUsage |= EXTKEYUSE_ANY;
03875                 break;
03876             case EKU_SERVER_AUTH_OID:
03877                 cert->extExtKeyUsage |= EXTKEYUSE_SERVER_AUTH;
03878                 break;
03879             case EKU_CLIENT_AUTH_OID:
03880                 cert->extExtKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
03881                 break;
03882             case EKU_OCSP_SIGN_OID:
03883                 cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN;
03884                 break;
03885         }
03886 
03887         #ifdef OPENSSL_EXTRA
03888             cert->extExtKeyUsageCount++;
03889         #endif
03890     }
03891 
03892     return 0;
03893 }
03894 
03895 
03896 #ifndef IGNORE_NAME_CONSTRAINTS
03897 static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
03898 {
03899     word32 idx = 0;
03900 
03901     (void)heap;
03902 
03903     while (idx < (word32)sz) {
03904         int seqLength, strLength;
03905         word32 nameIdx;
03906         byte b;
03907 
03908         if (GetSequence(input, &idx, &seqLength, sz) < 0) {
03909             CYASSL_MSG("\tfail: should be a SEQUENCE");
03910             return ASN_PARSE_E;
03911         }
03912 
03913         nameIdx = idx;
03914         b = input[nameIdx++];
03915         if (GetLength(input, &nameIdx, &strLength, sz) <= 0) {
03916             CYASSL_MSG("\tinvalid length");
03917             return ASN_PARSE_E;
03918         }
03919 
03920         if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE) ||
03921             b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE) ||
03922             b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) {
03923 
03924             Base_entry* entry = (Base_entry*)XMALLOC(sizeof(Base_entry),
03925                                                     heap, DYNAMIC_TYPE_ALTNAME);
03926 
03927             if (entry == NULL) {
03928                 CYASSL_MSG("allocate error");
03929                 return MEMORY_E;
03930             }
03931 
03932             entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME);
03933             if (entry->name == NULL) {
03934                 CYASSL_MSG("allocate error");
03935                 return MEMORY_E;
03936             }
03937 
03938             XMEMCPY(entry->name, &input[nameIdx], strLength);
03939             entry->nameSz = strLength;
03940             entry->type = b & 0x0F;
03941 
03942             entry->next = *head;
03943             *head = entry;
03944         }
03945 
03946         idx += seqLength;
03947     }
03948 
03949     return 0;
03950 }
03951 
03952 
03953 static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert)
03954 {
03955     word32 idx = 0;
03956     int length = 0;
03957 
03958     CYASSL_ENTER("DecodeNameConstraints");
03959 
03960     if (GetSequence(input, &idx, &length, sz) < 0) {
03961         CYASSL_MSG("\tfail: should be a SEQUENCE");
03962         return ASN_PARSE_E;
03963     }
03964 
03965     while (idx < (word32)sz) {
03966         byte b = input[idx++];
03967         Base_entry** subtree = NULL;
03968 
03969         if (GetLength(input, &idx, &length, sz) <= 0) {
03970             CYASSL_MSG("\tinvalid length");
03971             return ASN_PARSE_E;
03972         }
03973 
03974         if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0))
03975             subtree = &cert->permittedNames;
03976         else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
03977             subtree = &cert->excludedNames;
03978         else {
03979             CYASSL_MSG("\tinvalid subtree");
03980             return ASN_PARSE_E;
03981         }
03982 
03983         DecodeSubtree(input + idx, length, subtree, cert->heap);
03984 
03985         idx += length;
03986     }
03987 
03988     return 0;
03989 }
03990 #endif /* IGNORE_NAME_CONSTRAINTS */
03991 
03992 
03993 #ifdef CYASSL_SEP
03994     static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert)
03995     {
03996         word32 idx = 0;
03997         int length = 0;
03998 
03999         CYASSL_ENTER("DecodeCertPolicy");
04000 
04001         /* Unwrap certificatePolicies */
04002         if (GetSequence(input, &idx, &length, sz) < 0) {
04003             CYASSL_MSG("\tdeviceType isn't OID");
04004             return ASN_PARSE_E;
04005         }
04006 
04007         if (GetSequence(input, &idx, &length, sz) < 0) {
04008             CYASSL_MSG("\tdeviceType isn't OID");
04009             return ASN_PARSE_E;
04010         }
04011 
04012         if (input[idx++] != ASN_OBJECT_ID) {
04013             CYASSL_MSG("\tdeviceType isn't OID");
04014             return ASN_PARSE_E;
04015         }
04016 
04017         if (GetLength(input, &idx, &length, sz) < 0) {
04018             CYASSL_MSG("\tCouldn't read length of deviceType");
04019             return ASN_PARSE_E;
04020         }
04021 
04022         if (length > 0) {
04023             cert->deviceType = (byte*)XMALLOC(length, cert->heap, 0);
04024             if (cert->deviceType == NULL) {
04025                 CYASSL_MSG("\tCouldn't alloc memory for deviceType");
04026                 return MEMORY_E;
04027             }
04028             cert->deviceTypeSz = length;
04029             XMEMCPY(cert->deviceType, input + idx, length);
04030         }
04031 
04032         CYASSL_LEAVE("DecodeCertPolicy", 0);
04033         return 0;
04034     }
04035 #endif /* CYASSL_SEP */
04036 
04037 
04038 static int DecodeCertExtensions(DecodedCert* cert)
04039 /*
04040  *  Processing the Certificate Extensions. This does not modify the current
04041  *  index. It is works starting with the recorded extensions pointer.
04042  */
04043 {
04044     word32 idx = 0;
04045     int sz = cert->extensionsSz;
04046     byte* input = cert->extensions;
04047     int length;
04048     word32 oid;
04049     byte critical = 0;
04050     byte criticalFail = 0;
04051 
04052     CYASSL_ENTER("DecodeCertExtensions");
04053 
04054     if (input == NULL || sz == 0)
04055         return BAD_FUNC_ARG;
04056 
04057     if (input[idx++] != ASN_EXTENSIONS)
04058         return ASN_PARSE_E;
04059 
04060     if (GetLength(input, &idx, &length, sz) < 0)
04061         return ASN_PARSE_E;
04062 
04063     if (GetSequence(input, &idx, &length, sz) < 0)
04064         return ASN_PARSE_E;
04065     
04066     while (idx < (word32)sz) {
04067         if (GetSequence(input, &idx, &length, sz) < 0) {
04068             CYASSL_MSG("\tfail: should be a SEQUENCE");
04069             return ASN_PARSE_E;
04070         }
04071 
04072         oid = 0;
04073         if (GetObjectId(input, &idx, &oid, sz) < 0) {
04074             CYASSL_MSG("\tfail: OBJECT ID");
04075             return ASN_PARSE_E;
04076         }
04077 
04078         /* check for critical flag */
04079         critical = 0;
04080         if (input[idx] == ASN_BOOLEAN) {
04081             int boolLength = 0;
04082             idx++;
04083             if (GetLength(input, &idx, &boolLength, sz) < 0) {
04084                 CYASSL_MSG("\tfail: critical boolean length");
04085                 return ASN_PARSE_E;
04086             }
04087             if (input[idx++])
04088                 critical = 1;
04089         }
04090 
04091         /* process the extension based on the OID */
04092         if (input[idx++] != ASN_OCTET_STRING) {
04093             CYASSL_MSG("\tfail: should be an OCTET STRING");
04094             return ASN_PARSE_E;
04095         }
04096 
04097         if (GetLength(input, &idx, &length, sz) < 0) {
04098             CYASSL_MSG("\tfail: extension data length");
04099             return ASN_PARSE_E;
04100         }
04101 
04102         switch (oid) {
04103             case BASIC_CA_OID:
04104                 #ifdef OPENSSL_EXTRA
04105                     cert->extBasicConstSet = 1;
04106                     cert->extBasicConstCrit = critical;
04107                 #endif
04108                 if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0)
04109                     return ASN_PARSE_E;
04110                 break;
04111 
04112             case CRL_DIST_OID:
04113                 if (DecodeCrlDist(&input[idx], length, cert) < 0)
04114                     return ASN_PARSE_E;
04115                 break;
04116 
04117             case AUTH_INFO_OID:
04118                 if (DecodeAuthInfo(&input[idx], length, cert) < 0)
04119                     return ASN_PARSE_E;
04120                 break;
04121 
04122             case ALT_NAMES_OID:
04123                 #ifdef OPENSSL_EXTRA
04124                     cert->extSubjAltNameSet = 1;
04125                     cert->extSubjAltNameCrit = critical;
04126                 #endif
04127                 if (DecodeAltNames(&input[idx], length, cert) < 0)
04128                     return ASN_PARSE_E;
04129                 break;
04130 
04131             case AUTH_KEY_OID:
04132                 cert->extAuthKeyIdSet = 1;
04133                 #ifdef OPENSSL_EXTRA
04134                     cert->extAuthKeyIdCrit = critical;
04135                 #endif
04136                 if (DecodeAuthKeyId(&input[idx], length, cert) < 0)
04137                     return ASN_PARSE_E;
04138                 break;
04139 
04140             case SUBJ_KEY_OID:
04141                 cert->extSubjKeyIdSet = 1;
04142                 #ifdef OPENSSL_EXTRA
04143                     cert->extSubjKeyIdCrit = critical;
04144                 #endif
04145                 if (DecodeSubjKeyId(&input[idx], length, cert) < 0)
04146                     return ASN_PARSE_E;
04147                 break;
04148 
04149             case CERT_POLICY_OID:
04150                 CYASSL_MSG("Certificate Policy extension not supported yet.");
04151                 #ifdef CYASSL_SEP
04152                     #ifdef OPENSSL_EXTRA
04153                         cert->extCertPolicySet = 1;
04154                         cert->extCertPolicyCrit = critical;
04155                     #endif
04156                     if (DecodeCertPolicy(&input[idx], length, cert) < 0)
04157                         return ASN_PARSE_E;
04158                 #endif
04159                 break;
04160 
04161             case KEY_USAGE_OID:
04162                 cert->extKeyUsageSet = 1;
04163                 #ifdef OPENSSL_EXTRA
04164                     cert->extKeyUsageCrit = critical;
04165                 #endif
04166                 if (DecodeKeyUsage(&input[idx], length, cert) < 0)
04167                     return ASN_PARSE_E;
04168                 break;
04169 
04170             case EXT_KEY_USAGE_OID:
04171                 cert->extExtKeyUsageSet = 1;
04172                 #ifdef OPENSSL_EXTRA
04173                     cert->extExtKeyUsageCrit = critical;
04174                 #endif
04175                 if (DecodeExtKeyUsage(&input[idx], length, cert) < 0)
04176                     return ASN_PARSE_E;
04177                 break;
04178 
04179             #ifndef IGNORE_NAME_CONSTRAINTS
04180             case NAME_CONS_OID:
04181                 cert->extNameConstraintSet = 1;
04182                 #ifdef OPENSSL_EXTRA
04183                     cert->extNameConstraintCrit = critical;
04184                 #endif
04185                 if (DecodeNameConstraints(&input[idx], length, cert) < 0)
04186                     return ASN_PARSE_E;
04187                 break;
04188             #endif /* IGNORE_NAME_CONSTRAINTS */
04189 
04190             case INHIBIT_ANY_OID:
04191                 CYASSL_MSG("Inhibit anyPolicy extension not supported yet.");
04192                 break;
04193 
04194             default:
04195                 /* While it is a failure to not support critical extensions,
04196                  * still parse the certificate ignoring the unsupported
04197                  * extention to allow caller to accept it with the verify
04198                  * callback. */
04199                 if (critical)
04200                     criticalFail = 1;
04201                 break;
04202         }
04203         idx += length;
04204     }
04205 
04206     return criticalFail ? ASN_CRIT_EXT_E : 0;
04207 }
04208 
04209 
04210 int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
04211 {
04212     int   ret;
04213     char* ptr;
04214 
04215     ret = ParseCertRelative(cert, type, verify, cm);
04216     if (ret < 0)
04217         return ret;
04218 
04219     if (cert->subjectCNLen > 0) {
04220         ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap,
04221                               DYNAMIC_TYPE_SUBJECT_CN);
04222         if (ptr == NULL)
04223             return MEMORY_E;
04224         XMEMCPY(ptr, cert->subjectCN, cert->subjectCNLen);
04225         ptr[cert->subjectCNLen] = '\0';
04226         cert->subjectCN = ptr;
04227         cert->subjectCNStored = 1;
04228     }
04229 
04230     if (cert->keyOID == RSAk &&
04231                           cert->publicKey != NULL  && cert->pubKeySize > 0) {
04232         ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap,
04233                               DYNAMIC_TYPE_PUBLIC_KEY);
04234         if (ptr == NULL)
04235             return MEMORY_E;
04236         XMEMCPY(ptr, cert->publicKey, cert->pubKeySize);
04237         cert->publicKey = (byte *)ptr;
04238         cert->pubKeyStored = 1;
04239     }
04240 
04241     return ret;
04242 }
04243 
04244 
04245 /* from SSL proper, for locking can't do find here anymore */
04246 #ifdef __cplusplus
04247     extern "C" {
04248 #endif
04249     CYASSL_LOCAL Signer* GetCA(void* signers, byte* hash);
04250     #ifndef NO_SKID
04251         CYASSL_LOCAL Signer* GetCAByName(void* signers, byte* hash);
04252     #endif
04253 #ifdef __cplusplus
04254     } 
04255 #endif
04256 
04257 
04258 int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
04259 {
04260     word32 confirmOID;
04261     int    ret;
04262     int    badDate     = 0;
04263     int    criticalExt = 0;
04264 
04265     if ((ret = DecodeToKey(cert, verify)) < 0) {
04266         if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
04267             badDate = ret;
04268         else
04269             return ret;
04270     }
04271 
04272     CYASSL_MSG("Parsed Past Key");
04273 
04274     if (cert->srcIdx < cert->sigIndex) {
04275         #ifndef ALLOW_V1_EXTENSIONS
04276             if (cert->version < 2) {
04277                 CYASSL_MSG("    v1 and v2 certs not allowed extensions");
04278                 return ASN_VERSION_E;
04279             }
04280         #endif
04281         /* save extensions */
04282         cert->extensions    = &cert->source[cert->srcIdx];
04283         cert->extensionsSz  =  cert->sigIndex - cert->srcIdx;
04284         cert->extensionsIdx = cert->srcIdx;   /* for potential later use */
04285 
04286         if ((ret = DecodeCertExtensions(cert)) < 0) {
04287             if (ret == ASN_CRIT_EXT_E)
04288                 criticalExt = ret;
04289             else
04290                 return ret;
04291         }
04292 
04293         /* advance past extensions */
04294         cert->srcIdx =  cert->sigIndex;
04295     }
04296 
04297     if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
04298                          cert->maxIdx)) < 0)
04299         return ret;
04300 
04301     if ((ret = GetSignature(cert)) < 0)
04302         return ret;
04303 
04304     if (confirmOID != cert->signatureOID)
04305         return ASN_SIG_OID_E;
04306 
04307     #ifndef NO_SKID
04308         if (cert->extSubjKeyIdSet == 0
04309                           && cert->publicKey != NULL && cert->pubKeySize > 0) {
04310             Sha sha;
04311             ret = InitSha(&sha);
04312             if (ret != 0)
04313                 return ret;
04314             ShaUpdate(&sha, cert->publicKey, cert->pubKeySize);
04315             ShaFinal(&sha, cert->extSubjKeyId);
04316         }
04317     #endif
04318     if (verify && type != CA_TYPE) {
04319         Signer* ca = NULL;
04320         #ifndef NO_SKID
04321             if (cert->extAuthKeyIdSet)
04322                 ca = GetCA(cm, cert->extAuthKeyId);
04323             if (ca == NULL)
04324                 ca = GetCAByName(cm, cert->issuerHash);
04325         #else /* NO_SKID */
04326             ca = GetCA(cm, cert->issuerHash);
04327         #endif /* NO SKID */
04328         CYASSL_MSG("About to verify certificate signature");
04329         if (ca) {
04330 #ifdef HAVE_OCSP
04331             /* Need the ca's public key hash for OCSP */
04332             {
04333                 Sha sha;
04334                 ret = InitSha(&sha);
04335                 if (ret != 0)
04336                     return ret;
04337                 ShaUpdate(&sha, ca->publicKey, ca->pubKeySize);
04338                 ShaFinal(&sha, cert->issuerKeyHash);
04339             }
04340 #endif /* HAVE_OCSP */
04341             /* try to confirm/verify signature */
04342             if (!ConfirmSignature(cert->source + cert->certBegin,
04343                         cert->sigIndex - cert->certBegin,
04344                     ca->publicKey, ca->pubKeySize, ca->keyOID,
04345                     cert->signature, cert->sigLength, cert->signatureOID,
04346                     cert->heap)) {
04347                 CYASSL_MSG("Confirm signature failed");
04348                 return ASN_SIG_CONFIRM_E;
04349             }
04350 #ifndef IGNORE_NAME_CONSTRAINTS
04351             /* check that this cert's name is permitted by the signer's
04352              * name constraints */
04353             if (!ConfirmNameConstraints(ca, cert)) {
04354                 CYASSL_MSG("Confirm name constraint failed");
04355                 return ASN_NAME_INVALID_E;
04356             }
04357 #endif /* IGNORE_NAME_CONSTRAINTS */
04358         }
04359         else {
04360             /* no signer */
04361             CYASSL_MSG("No CA signer to verify with");
04362             return ASN_NO_SIGNER_E;
04363         }
04364     }
04365 
04366     if (badDate != 0)
04367         return badDate;
04368 
04369     if (criticalExt != 0)
04370         return criticalExt;
04371 
04372     return 0;
04373 }
04374 
04375 
04376 /* Create and init an new signer */
04377 Signer* MakeSigner(void* heap)
04378 {
04379     Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap,
04380                                        DYNAMIC_TYPE_SIGNER);
04381     if (signer) {
04382         signer->pubKeySize = 0;
04383         signer->keyOID     = 0;
04384         signer->publicKey  = NULL;
04385         signer->nameLen    = 0;
04386         signer->name       = NULL;
04387         #ifndef IGNORE_NAME_CONSTRAINTS
04388             signer->permittedNames = NULL;
04389             signer->excludedNames = NULL;
04390         #endif /* IGNORE_NAME_CONSTRAINTS */
04391         signer->next       = NULL;
04392     }
04393     (void)heap;
04394 
04395     return signer;
04396 }
04397 
04398 
04399 /* Free an individual signer */
04400 void FreeSigner(Signer* signer, void* heap)
04401 {
04402     XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
04403     XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
04404     #ifndef IGNORE_NAME_CONSTRAINTS
04405         if (signer->permittedNames)
04406             FreeNameSubtrees(signer->permittedNames, heap);
04407         if (signer->excludedNames)
04408             FreeNameSubtrees(signer->excludedNames, heap);
04409     #endif
04410     XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
04411 
04412     (void)heap;
04413 }
04414 
04415 
04416 /* Free the whole singer table with number of rows */
04417 void FreeSignerTable(Signer** table, int rows, void* heap)
04418 {
04419     int i;
04420 
04421     for (i = 0; i < rows; i++) {
04422         Signer* signer = table[i];
04423         while (signer) {
04424             Signer* next = signer->next;
04425             FreeSigner(signer, heap);
04426             signer = next;
04427         }
04428         table[i] = NULL;
04429     }
04430 }
04431 
04432 
04433 CYASSL_LOCAL int SetMyVersion(word32 version, byte* output, int header)
04434 {
04435     int i = 0;
04436 
04437     if (header) {
04438         output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
04439         output[i++] = ASN_BIT_STRING;
04440     }
04441     output[i++] = ASN_INTEGER;
04442     output[i++] = 0x01;
04443     output[i++] = (byte)version;
04444 
04445     return i;
04446 }
04447 
04448 
04449 CYASSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output)
04450 {
04451     int result = 0;
04452 
04453     CYASSL_ENTER("SetSerialNumber");
04454 
04455     if (snSz <= EXTERNAL_SERIAL_SIZE) {
04456         output[0] = ASN_INTEGER;
04457         /* The serial number is always positive. When encoding the
04458          * INTEGER, if the MSB is 1, add a padding zero to keep the
04459          * number positive. */
04460         if (sn[0] & 0x80) {
04461             output[1] = (byte)snSz + 1;
04462             output[2] = 0;
04463             XMEMCPY(&output[3], sn, snSz);
04464             result = snSz + 3;
04465         }
04466         else {
04467             output[1] = (byte)snSz;
04468             XMEMCPY(&output[2], sn, snSz);
04469             result = snSz + 2;
04470         }
04471     }
04472     return result;
04473 }
04474 
04475 
04476 
04477 
04478 #if defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN)
04479 
04480 /* convert der buffer to pem into output, can't do inplace, der and output
04481    need to be different */
04482 int DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
04483              int type)
04484 {
04485 #ifdef CYASSL_SMALL_STACK
04486     char* header = NULL;
04487     char* footer = NULL;
04488 #else
04489     char header[80];
04490     char footer[80];
04491 #endif
04492 
04493     int headerLen = 80;
04494     int footerLen = 80;
04495     int i;
04496     int err;
04497     int outLen;   /* return length or error */
04498 
04499     if (der == output)      /* no in place conversion */
04500         return BAD_FUNC_ARG;
04501 
04502 #ifdef CYASSL_SMALL_STACK
04503     header = (char*)XMALLOC(headerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04504     if (header == NULL)
04505         return MEMORY_E;
04506     
04507     footer = (char*)XMALLOC(footerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04508     if (footer == NULL) {
04509         XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04510         return MEMORY_E;
04511     }
04512 #endif
04513 
04514     if (type == CERT_TYPE) {
04515         XSTRNCPY(header, "-----BEGIN CERTIFICATE-----\n", headerLen);
04516         XSTRNCPY(footer, "-----END CERTIFICATE-----\n",   footerLen);
04517     }
04518     else if (type == PRIVATEKEY_TYPE) {
04519         XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----\n", headerLen);
04520         XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----\n",   footerLen);
04521     }
04522     #ifdef HAVE_ECC
04523     else if (type == ECC_PRIVATEKEY_TYPE) {
04524         XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----\n", headerLen);
04525         XSTRNCPY(footer, "-----END EC PRIVATE KEY-----\n",   footerLen);
04526     }
04527     #endif
04528     #ifdef CYASSL_CERT_REQ
04529     else if (type == CERTREQ_TYPE)
04530     {
04531         XSTRNCPY(header,
04532                        "-----BEGIN CERTIFICATE REQUEST-----\n", headerLen);
04533         XSTRNCPY(footer, "-----END CERTIFICATE REQUEST-----\n", footerLen);
04534     }
04535     #endif
04536     else {
04537 #ifdef CYASSL_SMALL_STACK
04538         XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04539         XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04540 #endif
04541         return BAD_FUNC_ARG;
04542     }
04543 
04544     headerLen = (int)XSTRLEN(header);
04545     footerLen = (int)XSTRLEN(footer);
04546 
04547     if (!der || !output) {
04548 #ifdef CYASSL_SMALL_STACK
04549         XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04550         XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04551 #endif
04552         return BAD_FUNC_ARG;
04553     }
04554 
04555     /* don't even try if outSz too short */
04556     if (outSz < headerLen + footerLen + derSz) {
04557 #ifdef CYASSL_SMALL_STACK
04558         XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04559         XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04560 #endif
04561         return BAD_FUNC_ARG;
04562     }
04563 
04564     /* header */
04565     XMEMCPY(output, header, headerLen);
04566     i = headerLen;
04567 
04568 #ifdef CYASSL_SMALL_STACK
04569     XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04570 #endif
04571 
04572     /* body */
04573     outLen = outSz - (headerLen + footerLen);  /* input to Base64_Encode */
04574     if ( (err = Base64_Encode(der, derSz, output + i, (word32*)&outLen)) < 0) {
04575 #ifdef CYASSL_SMALL_STACK
04576         XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04577 #endif
04578         return err;
04579     }
04580     i += outLen;
04581 
04582     /* footer */
04583     if ( (i + footerLen) > (int)outSz) {
04584 #ifdef CYASSL_SMALL_STACK
04585         XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04586 #endif
04587         return BAD_FUNC_ARG;
04588     }
04589     XMEMCPY(output + i, footer, footerLen);
04590 
04591 #ifdef CYASSL_SMALL_STACK
04592     XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04593 #endif
04594 
04595     return outLen + headerLen + footerLen;
04596 }
04597 
04598 
04599 #endif /* CYASSL_KEY_GEN || CYASSL_CERT_GEN */
04600 
04601 
04602 #if defined(CYASSL_KEY_GEN) && !defined(NO_RSA)
04603 
04604 
04605 static mp_int* GetRsaInt(RsaKey* key, int idx)
04606 {
04607     if (idx == 0)
04608         return &key->n;
04609     if (idx == 1)
04610         return &key->e;
04611     if (idx == 2)
04612         return &key->d;
04613     if (idx == 3)
04614         return &key->p;
04615     if (idx == 4)
04616         return &key->q;
04617     if (idx == 5)
04618         return &key->dP;
04619     if (idx == 6)
04620         return &key->dQ;
04621     if (idx == 7)
04622         return &key->u;
04623 
04624     return NULL;
04625 }
04626 
04627 
04628 /* Release Tmp RSA resources */
04629 static INLINE void FreeTmpRsas(byte** tmps, void* heap)
04630 {
04631     int i;
04632 
04633     (void)heap;
04634 
04635     for (i = 0; i < RSA_INTS; i++) 
04636         XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA);
04637 }
04638 
04639 
04640 /* Convert RsaKey key to DER format, write to output (inLen), return bytes
04641    written */
04642 int RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
04643 {
04644     word32 seqSz, verSz, rawLen, intTotalLen = 0;
04645     word32 sizes[RSA_INTS];
04646     int    i, j, outLen, ret = 0;
04647 
04648     byte  seq[MAX_SEQ_SZ];
04649     byte  ver[MAX_VERSION_SZ];
04650     byte* tmps[RSA_INTS];
04651 
04652     if (!key || !output)
04653         return BAD_FUNC_ARG;
04654 
04655     if (key->type != RSA_PRIVATE)
04656         return BAD_FUNC_ARG;
04657 
04658     for (i = 0; i < RSA_INTS; i++)
04659         tmps[i] = NULL;
04660 
04661     /* write all big ints from key to DER tmps */
04662     for (i = 0; i < RSA_INTS; i++) {
04663         mp_int* keyInt = GetRsaInt(key, i);
04664         rawLen = mp_unsigned_bin_size(keyInt);
04665         tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
04666                                  DYNAMIC_TYPE_RSA);
04667         if (tmps[i] == NULL) {
04668             ret = MEMORY_E;
04669             break;
04670         }
04671 
04672         tmps[i][0] = ASN_INTEGER;
04673         sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1;  /* int tag */
04674 
04675         if (sizes[i] <= MAX_SEQ_SZ) {
04676             int err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]);
04677             if (err == MP_OKAY) {
04678                 sizes[i] += rawLen;
04679                 intTotalLen += sizes[i];
04680             }
04681             else {
04682                 ret = err;
04683                 break;
04684             }
04685         }
04686         else {
04687             ret = ASN_INPUT_E;
04688             break;
04689         }
04690     }
04691 
04692     if (ret != 0) {
04693         FreeTmpRsas(tmps, key->heap);
04694         return ret;
04695     }
04696 
04697     /* make headers */
04698     verSz = SetMyVersion(0, ver, FALSE);
04699     seqSz = SetSequence(verSz + intTotalLen, seq);
04700 
04701     outLen = seqSz + verSz + intTotalLen;
04702     if (outLen > (int)inLen)
04703         return BAD_FUNC_ARG;
04704 
04705     /* write to output */
04706     XMEMCPY(output, seq, seqSz);
04707     j = seqSz;
04708     XMEMCPY(output + j, ver, verSz);
04709     j += verSz;
04710 
04711     for (i = 0; i < RSA_INTS; i++) {
04712         XMEMCPY(output + j, tmps[i], sizes[i]);
04713         j += sizes[i];
04714     }
04715     FreeTmpRsas(tmps, key->heap);
04716 
04717     return outLen;
04718 }
04719 
04720 #endif /* CYASSL_KEY_GEN && !NO_RSA */
04721 
04722 
04723 #if defined(CYASSL_CERT_GEN) && !defined(NO_RSA)
04724 
04725 
04726 #ifndef min
04727 
04728     static INLINE word32 min(word32 a, word32 b)
04729     {
04730         return a > b ? b : a;
04731     }
04732 
04733 #endif /* min */
04734 
04735 
04736 /* Initialize and Set Certficate defaults:
04737    version    = 3 (0x2)
04738    serial     = 0
04739    sigType    = SHA_WITH_RSA
04740    issuer     = blank
04741    daysValid  = 500
04742    selfSigned = 1 (true) use subject as issuer
04743    subject    = blank
04744 */
04745 void InitCert(Cert* cert)
04746 {
04747     cert->version    = 2;   /* version 3 is hex 2 */
04748     cert->sigType    = CTC_SHAwRSA;
04749     cert->daysValid  = 500;
04750     cert->selfSigned = 1;
04751     cert->isCA       = 0;
04752     cert->bodySz     = 0;
04753 #ifdef CYASSL_ALT_NAMES
04754     cert->altNamesSz   = 0;
04755     cert->beforeDateSz = 0;
04756     cert->afterDateSz  = 0;
04757 #endif
04758     cert->keyType    = RSA_KEY;
04759     XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE);
04760 
04761     cert->issuer.country[0] = '\0';
04762     cert->issuer.countryEnc = CTC_PRINTABLE;
04763     cert->issuer.state[0] = '\0';
04764     cert->issuer.stateEnc = CTC_UTF8;
04765     cert->issuer.locality[0] = '\0';
04766     cert->issuer.localityEnc = CTC_UTF8;
04767     cert->issuer.sur[0] = '\0';
04768     cert->issuer.surEnc = CTC_UTF8;
04769     cert->issuer.org[0] = '\0';
04770     cert->issuer.orgEnc = CTC_UTF8;
04771     cert->issuer.unit[0] = '\0';
04772     cert->issuer.unitEnc = CTC_UTF8;
04773     cert->issuer.commonName[0] = '\0';
04774     cert->issuer.commonNameEnc = CTC_UTF8;
04775     cert->issuer.email[0] = '\0';
04776 
04777     cert->subject.country[0] = '\0';
04778     cert->subject.countryEnc = CTC_PRINTABLE;
04779     cert->subject.state[0] = '\0';
04780     cert->subject.stateEnc = CTC_UTF8;
04781     cert->subject.locality[0] = '\0';
04782     cert->subject.localityEnc = CTC_UTF8;
04783     cert->subject.sur[0] = '\0';
04784     cert->subject.surEnc = CTC_UTF8;
04785     cert->subject.org[0] = '\0';
04786     cert->subject.orgEnc = CTC_UTF8;
04787     cert->subject.unit[0] = '\0';
04788     cert->subject.unitEnc = CTC_UTF8;
04789     cert->subject.commonName[0] = '\0';
04790     cert->subject.commonNameEnc = CTC_UTF8;
04791     cert->subject.email[0] = '\0';
04792 
04793 #ifdef CYASSL_CERT_REQ
04794     cert->challengePw[0] ='\0';
04795 #endif
04796 }
04797 
04798 
04799 /* DER encoded x509 Certificate */
04800 typedef struct DerCert {
04801     byte size[MAX_LENGTH_SZ];          /* length encoded */
04802     byte version[MAX_VERSION_SZ];      /* version encoded */
04803     byte serial[CTC_SERIAL_SIZE + MAX_LENGTH_SZ]; /* serial number encoded */
04804     byte sigAlgo[MAX_ALGO_SZ];         /* signature algo encoded */
04805     byte issuer[ASN_NAME_MAX];         /* issuer  encoded */
04806     byte subject[ASN_NAME_MAX];        /* subject encoded */
04807     byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2];  /* before and after dates */
04808     byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */
04809     byte ca[MAX_CA_SZ];                /* basic constraint CA true size */
04810     byte extensions[MAX_EXTENSIONS_SZ];  /* all extensions */
04811 #ifdef CYASSL_CERT_REQ
04812     byte attrib[MAX_ATTRIB_SZ];        /* Cert req attributes encoded */
04813 #endif
04814     int  sizeSz;                       /* encoded size length */
04815     int  versionSz;                    /* encoded version length */
04816     int  serialSz;                     /* encoded serial length */
04817     int  sigAlgoSz;                    /* enocded sig alog length */
04818     int  issuerSz;                     /* encoded issuer length */
04819     int  subjectSz;                    /* encoded subject length */
04820     int  validitySz;                   /* encoded validity length */
04821     int  publicKeySz;                  /* encoded public key length */
04822     int  caSz;                         /* encoded CA extension length */
04823     int  extensionsSz;                 /* encoded extensions total length */
04824     int  total;                        /* total encoded lengths */
04825 #ifdef CYASSL_CERT_REQ
04826     int  attribSz;
04827 #endif
04828 } DerCert;
04829 
04830 
04831 #ifdef CYASSL_CERT_REQ
04832 
04833 /* Write a set header to output */
04834 static word32 SetUTF8String(word32 len, byte* output)
04835 {
04836     output[0] = ASN_UTF8STRING;
04837     return SetLength(len, output + 1) + 1;
04838 }
04839 
04840 #endif /* CYASSL_CERT_REQ */
04841 
04842 
04843 /* Write a serial number to output */
04844 static int SetSerial(const byte* serial, byte* output)
04845 {
04846     int length = 0;
04847 
04848     output[length++] = ASN_INTEGER;
04849     length += SetLength(CTC_SERIAL_SIZE, &output[length]);
04850     XMEMCPY(&output[length], serial, CTC_SERIAL_SIZE);
04851 
04852     return length + CTC_SERIAL_SIZE;
04853 }
04854 
04855 
04856 #ifdef HAVE_ECC 
04857 
04858 
04859 /* Write a public ECC key to output */
04860 static int SetEccPublicKey(byte* output, ecc_key* key)
04861 {
04862     byte len[MAX_LENGTH_SZ + 1];  /* trailing 0 */
04863     int  algoSz;
04864     int  curveSz;
04865     int  lenSz;
04866     int  idx;
04867     word32 pubSz = ECC_BUFSIZE;
04868 #ifdef CYASSL_SMALL_STACK
04869     byte* algo = NULL;
04870     byte* curve = NULL;
04871     byte* pub = NULL;
04872 #else
04873     byte algo[MAX_ALGO_SZ];
04874     byte curve[MAX_ALGO_SZ];
04875     byte pub[ECC_BUFSIZE];
04876 #endif
04877 
04878 #ifdef CYASSL_SMALL_STACK
04879     pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04880     if (pub == NULL)
04881         return MEMORY_E;
04882 #endif
04883 
04884     int ret = ecc_export_x963(key, pub, &pubSz);
04885     if (ret != 0) {
04886 #ifdef CYASSL_SMALL_STACK
04887         XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04888 #endif
04889         return ret;
04890     }
04891 
04892 #ifdef CYASSL_SMALL_STACK
04893     curve = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04894     if (curve == NULL) {
04895         XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04896         return MEMORY_E;
04897     }
04898 #endif
04899 
04900     /* headers */
04901     curveSz = SetCurve(key, curve);
04902     if (curveSz <= 0) {
04903 #ifdef CYASSL_SMALL_STACK
04904         XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04905         XFREE(pub,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
04906 #endif
04907         return curveSz;
04908     }
04909 
04910 #ifdef CYASSL_SMALL_STACK
04911     algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04912     if (algo == NULL) {
04913         XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04914         XFREE(pub,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
04915         return MEMORY_E;
04916     }
04917 #endif
04918 
04919     algoSz  = SetAlgoID(ECDSAk, algo, keyType, curveSz);
04920     lenSz   = SetLength(pubSz + 1, len);
04921     len[lenSz++] = 0;   /* trailing 0 */
04922 
04923     /* write */
04924     idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output);
04925         /* 1 is for ASN_BIT_STRING */
04926     /* algo */
04927     XMEMCPY(output + idx, algo, algoSz);
04928     idx += algoSz;
04929     /* curve */
04930     XMEMCPY(output + idx, curve, curveSz);
04931     idx += curveSz;
04932     /* bit string */
04933     output[idx++] = ASN_BIT_STRING;
04934     /* length */
04935     XMEMCPY(output + idx, len, lenSz);
04936     idx += lenSz;
04937     /* pub */
04938     XMEMCPY(output + idx, pub, pubSz);
04939     idx += pubSz;
04940 
04941 #ifdef CYASSL_SMALL_STACK
04942     XFREE(algo,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
04943     XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04944     XFREE(pub,   NULL, DYNAMIC_TYPE_TMP_BUFFER);
04945 #endif
04946 
04947     return idx;
04948 }
04949 
04950 
04951 #endif /* HAVE_ECC */
04952 
04953 
04954 /* Write a public RSA key to output */
04955 static int SetRsaPublicKey(byte* output, RsaKey* key)
04956 {
04957 #ifdef CYASSL_SMALL_STACK
04958     byte* n = NULL;
04959     byte* e = NULL;
04960     byte* algo = NULL;
04961 #else
04962     byte n[MAX_RSA_INT_SZ];
04963     byte e[MAX_RSA_E_SZ];
04964     byte algo[MAX_ALGO_SZ];
04965 #endif
04966     byte seq[MAX_SEQ_SZ];
04967     byte len[MAX_LENGTH_SZ + 1];  /* trailing 0 */
04968     int  nSz;
04969     int  eSz;
04970     int  algoSz;
04971     int  seqSz;
04972     int  lenSz;
04973     int  idx;
04974     int  rawLen;
04975     int  leadingBit;
04976     int  err;
04977 
04978     /* n */
04979 #ifdef CYASSL_SMALL_STACK
04980     n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04981     if (n == NULL)
04982         return MEMORY_E;
04983 #endif
04984 
04985     leadingBit = mp_leading_bit(&key->n);
04986     rawLen = mp_unsigned_bin_size(&key->n) + leadingBit;
04987     n[0] = ASN_INTEGER;
04988     nSz  = SetLength(rawLen, n + 1) + 1;  /* int tag */
04989 
04990     if ( (nSz + rawLen) < MAX_RSA_INT_SZ) {
04991         if (leadingBit)
04992             n[nSz] = 0;
04993         err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit);
04994         if (err == MP_OKAY)
04995             nSz += rawLen;
04996         else {
04997 #ifdef CYASSL_SMALL_STACK
04998             XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04999 #endif
05000             return MP_TO_E;
05001         }
05002     }
05003     else {
05004 #ifdef CYASSL_SMALL_STACK
05005         XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05006 #endif
05007         return BUFFER_E;
05008     }
05009 
05010     /* e */
05011 #ifdef CYASSL_SMALL_STACK
05012     e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05013     if (e == NULL) {
05014 #ifdef CYASSL_SMALL_STACK
05015         XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05016 #endif
05017         return MEMORY_E;
05018     }
05019 #endif
05020 
05021     leadingBit = mp_leading_bit(&key->e);
05022     rawLen = mp_unsigned_bin_size(&key->e) + leadingBit;
05023     e[0] = ASN_INTEGER;
05024     eSz  = SetLength(rawLen, e + 1) + 1;  /* int tag */
05025 
05026     if ( (eSz + rawLen) < MAX_RSA_E_SZ) {
05027         if (leadingBit)
05028             e[eSz] = 0;
05029         err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit);
05030         if (err == MP_OKAY)
05031             eSz += rawLen;
05032         else {
05033 #ifdef CYASSL_SMALL_STACK
05034             XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05035             XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05036 #endif
05037             return MP_TO_E;
05038         }
05039     }
05040     else {
05041 #ifdef CYASSL_SMALL_STACK
05042         XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05043         XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05044 #endif
05045         return BUFFER_E;
05046     }
05047 
05048 #ifdef CYASSL_SMALL_STACK
05049     algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05050     if (algo == NULL) {
05051         XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05052         XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05053         return MEMORY_E;
05054     }
05055 #endif
05056 
05057     /* headers */
05058     algoSz = SetAlgoID(RSAk, algo, keyType, 0);
05059     seqSz  = SetSequence(nSz + eSz, seq);
05060     lenSz  = SetLength(seqSz + nSz + eSz + 1, len);
05061     len[lenSz++] = 0;   /* trailing 0 */
05062 
05063     /* write */
05064     idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output);
05065         /* 1 is for ASN_BIT_STRING */
05066     /* algo */
05067     XMEMCPY(output + idx, algo, algoSz);
05068     idx += algoSz;
05069     /* bit string */
05070     output[idx++] = ASN_BIT_STRING;
05071     /* length */
05072     XMEMCPY(output + idx, len, lenSz);
05073     idx += lenSz;
05074     /* seq */
05075     XMEMCPY(output + idx, seq, seqSz);
05076     idx += seqSz;
05077     /* n */
05078     XMEMCPY(output + idx, n, nSz);
05079     idx += nSz;
05080     /* e */
05081     XMEMCPY(output + idx, e, eSz);
05082     idx += eSz;
05083 
05084 #ifdef CYASSL_SMALL_STACK
05085     XFREE(n,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
05086     XFREE(e,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
05087     XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05088 #endif
05089 
05090     return idx;
05091 }
05092 
05093 
05094 static INLINE byte itob(int number)
05095 {
05096     return (byte)number + 0x30;
05097 }
05098 
05099 
05100 /* write time to output, format */
05101 static void SetTime(struct tm* date, byte* output)
05102 {
05103     int i = 0;
05104 
05105     output[i++] = itob((date->tm_year % 10000) / 1000);
05106     output[i++] = itob((date->tm_year % 1000)  /  100);
05107     output[i++] = itob((date->tm_year % 100)   /   10);
05108     output[i++] = itob( date->tm_year % 10);
05109 
05110     output[i++] = itob(date->tm_mon / 10);
05111     output[i++] = itob(date->tm_mon % 10);
05112 
05113     output[i++] = itob(date->tm_mday / 10);
05114     output[i++] = itob(date->tm_mday % 10);
05115 
05116     output[i++] = itob(date->tm_hour / 10);
05117     output[i++] = itob(date->tm_hour % 10);
05118 
05119     output[i++] = itob(date->tm_min / 10);
05120     output[i++] = itob(date->tm_min % 10);
05121 
05122     output[i++] = itob(date->tm_sec / 10);
05123     output[i++] = itob(date->tm_sec % 10);
05124     
05125     output[i] = 'Z';  /* Zulu profile */
05126 }
05127 
05128 
05129 #ifdef CYASSL_ALT_NAMES
05130 
05131 /* Copy Dates from cert, return bytes written */
05132 static int CopyValidity(byte* output, Cert* cert)
05133 {
05134     int seqSz;
05135 
05136     CYASSL_ENTER("CopyValidity");
05137 
05138     /* headers and output */
05139     seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output);
05140     XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
05141     XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
05142                                                  cert->afterDateSz);
05143     return seqSz + cert->beforeDateSz + cert->afterDateSz;
05144 }
05145 
05146 #endif
05147 
05148 
05149 /* Set Date validity from now until now + daysValid */
05150 static int SetValidity(byte* output, int daysValid)
05151 {
05152     byte before[MAX_DATE_SIZE];
05153     byte  after[MAX_DATE_SIZE];
05154 
05155     int beforeSz;
05156     int afterSz;
05157     int seqSz;
05158 
05159     time_t     ticks;
05160     struct tm* now;
05161     struct tm  local;
05162 
05163     ticks = XTIME(0);
05164     now   = XGMTIME(&ticks);
05165 
05166     /* before now */
05167     local = *now;
05168     before[0] = ASN_GENERALIZED_TIME;
05169     beforeSz  = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1;  /* gen tag */
05170 
05171     /* subtract 1 day for more compliance */
05172     local.tm_mday -= 1;
05173     mktime(&local);
05174 
05175     /* adjust */
05176     local.tm_year += 1900;
05177     local.tm_mon  +=    1;
05178 
05179     SetTime(&local, before + beforeSz);
05180     beforeSz += ASN_GEN_TIME_SZ;
05181     
05182     /* after now + daysValid */
05183     local = *now;
05184     after[0] = ASN_GENERALIZED_TIME;
05185     afterSz  = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1;  /* gen tag */
05186 
05187     /* add daysValid */
05188     local.tm_mday += daysValid;
05189     mktime(&local);
05190 
05191     /* adjust */
05192     local.tm_year += 1900;
05193     local.tm_mon  +=    1;
05194 
05195     SetTime(&local, after + afterSz);
05196     afterSz += ASN_GEN_TIME_SZ;
05197 
05198     /* headers and output */
05199     seqSz = SetSequence(beforeSz + afterSz, output);
05200     XMEMCPY(output + seqSz, before, beforeSz);
05201     XMEMCPY(output + seqSz + beforeSz, after, afterSz);
05202 
05203     return seqSz + beforeSz + afterSz;
05204 }
05205 
05206 
05207 /* ASN Encoded Name field */
05208 typedef struct EncodedName {
05209     int  nameLen;                /* actual string value length */
05210     int  totalLen;               /* total encoded length */
05211     int  type;                   /* type of name */
05212     int  used;                   /* are we actually using this one */
05213     byte encoded[CTC_NAME_SIZE * 2]; /* encoding */
05214 } EncodedName;
05215 
05216 
05217 /* Get Which Name from index */
05218 static const char* GetOneName(CertName* name, int idx)
05219 {
05220     switch (idx) {
05221     case 0:
05222        return name->country;
05223 
05224     case 1:
05225        return name->state;
05226 
05227     case 2:
05228        return name->locality;
05229 
05230     case 3:
05231        return name->sur;
05232 
05233     case 4:
05234        return name->org;
05235 
05236     case 5:
05237        return name->unit;
05238 
05239     case 6:
05240        return name->commonName;
05241 
05242     case 7:
05243        return name->email;
05244 
05245     default:
05246        return 0;
05247     }
05248 }
05249 
05250 
05251 /* Get Which Name Encoding from index */
05252 static char GetNameType(CertName* name, int idx)
05253 {
05254     switch (idx) {
05255     case 0:
05256        return name->countryEnc;
05257 
05258     case 1:
05259        return name->stateEnc;
05260 
05261     case 2:
05262        return name->localityEnc;
05263 
05264     case 3:
05265        return name->surEnc;
05266 
05267     case 4:
05268        return name->orgEnc;
05269 
05270     case 5:
05271        return name->unitEnc;
05272 
05273     case 6:
05274        return name->commonNameEnc;
05275 
05276     default:
05277        return 0;
05278     }
05279 }
05280 
05281 
05282 /* Get ASN Name from index */
05283 static byte GetNameId(int idx)
05284 {
05285     switch (idx) {
05286     case 0:
05287        return ASN_COUNTRY_NAME;
05288 
05289     case 1:
05290        return ASN_STATE_NAME;
05291 
05292     case 2:
05293        return ASN_LOCALITY_NAME;
05294 
05295     case 3:
05296        return ASN_SUR_NAME;
05297 
05298     case 4:
05299        return ASN_ORG_NAME;
05300 
05301     case 5:
05302        return ASN_ORGUNIT_NAME;
05303 
05304     case 6:
05305        return ASN_COMMON_NAME;
05306 
05307     case 7:
05308        /* email uses different id type */
05309        return 0;
05310 
05311     default:
05312        return 0;
05313     }
05314 }
05315 
05316 
05317 /* encode all extensions, return total bytes written */
05318 static int SetExtensions(byte* output, const byte* ext, int extSz, int header)
05319 {
05320     byte sequence[MAX_SEQ_SZ];
05321     byte len[MAX_LENGTH_SZ];
05322 
05323     int sz = 0;
05324     int seqSz = SetSequence(extSz, sequence);
05325 
05326     if (header) {
05327         int lenSz = SetLength(seqSz + extSz, len);
05328         output[0] = ASN_EXTENSIONS; /* extensions id */
05329         sz++;
05330         XMEMCPY(&output[sz], len, lenSz);  /* length */
05331         sz += lenSz;
05332     }
05333     XMEMCPY(&output[sz], sequence, seqSz);  /* sequence */
05334     sz += seqSz;
05335     XMEMCPY(&output[sz], ext, extSz);  /* extensions */
05336     sz += extSz;
05337 
05338     return sz;
05339 }
05340 
05341 
05342 /* encode CA basic constraint true, return total bytes written */
05343 static int SetCa(byte* output)
05344 {
05345     static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
05346                                0x05, 0x30, 0x03, 0x01, 0x01, 0xff };
05347     
05348     XMEMCPY(output, ca, sizeof(ca));
05349 
05350     return (int)sizeof(ca);
05351 }
05352 
05353 
05354 /* encode CertName into output, return total bytes written */
05355 static int SetName(byte* output, CertName* name)
05356 {
05357     int          totalBytes = 0, i, idx;
05358 #ifdef CYASSL_SMALL_STACK
05359     EncodedName* names = NULL;
05360 #else
05361     EncodedName  names[NAME_ENTRIES];
05362 #endif
05363 
05364 #ifdef CYASSL_SMALL_STACK
05365     names = (EncodedName*)XMALLOC(sizeof(EncodedName) * NAME_ENTRIES, NULL,
05366                                                        DYNAMIC_TYPE_TMP_BUFFER);
05367     if (names == NULL)
05368         return MEMORY_E;
05369 #endif
05370 
05371     for (i = 0; i < NAME_ENTRIES; i++) {
05372         const char* nameStr = GetOneName(name, i);
05373         if (nameStr) {
05374             /* bottom up */
05375             byte firstLen[MAX_LENGTH_SZ];
05376             byte secondLen[MAX_LENGTH_SZ];
05377             byte sequence[MAX_SEQ_SZ];
05378             byte set[MAX_SET_SZ];
05379 
05380             int email = i == (NAME_ENTRIES - 1) ? 1 : 0;
05381             int strLen  = (int)XSTRLEN(nameStr);
05382             int thisLen = strLen;
05383             int firstSz, secondSz, seqSz, setSz;
05384 
05385             if (strLen == 0) { /* no user data for this item */
05386                 names[i].used = 0;
05387                 continue;
05388             }
05389 
05390             secondSz = SetLength(strLen, secondLen);
05391             thisLen += secondSz;
05392             if (email) {
05393                 thisLen += EMAIL_JOINT_LEN;
05394                 thisLen ++;                               /* id type */
05395                 firstSz  = SetLength(EMAIL_JOINT_LEN, firstLen);
05396             }
05397             else {
05398                 thisLen++;                                 /* str type */
05399                 thisLen++;                                 /* id  type */
05400                 thisLen += JOINT_LEN;    
05401                 firstSz = SetLength(JOINT_LEN + 1, firstLen);
05402             }
05403             thisLen += firstSz;
05404             thisLen++;                                /* object id */
05405 
05406             seqSz = SetSequence(thisLen, sequence);
05407             thisLen += seqSz;
05408             setSz = SetSet(thisLen, set);
05409             thisLen += setSz;
05410 
05411             if (thisLen > (int)sizeof(names[i].encoded)) {
05412 #ifdef CYASSL_SMALL_STACK
05413                 XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05414 #endif
05415                 return BUFFER_E;
05416             }
05417 
05418             /* store it */
05419             idx = 0;
05420             /* set */
05421             XMEMCPY(names[i].encoded, set, setSz);
05422             idx += setSz;
05423             /* seq */
05424             XMEMCPY(names[i].encoded + idx, sequence, seqSz);
05425             idx += seqSz;
05426             /* asn object id */
05427             names[i].encoded[idx++] = ASN_OBJECT_ID;
05428             /* first length */
05429             XMEMCPY(names[i].encoded + idx, firstLen, firstSz);
05430             idx += firstSz;
05431             if (email) {
05432                 const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
05433                                            0x01, 0x09, 0x01, 0x16 };
05434                 /* email joint id */
05435                 XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
05436                 idx += (int)sizeof(EMAIL_OID);
05437             }
05438             else {
05439                 /* joint id */
05440                 byte bType = GetNameId(i);
05441                 names[i].encoded[idx++] = 0x55;
05442                 names[i].encoded[idx++] = 0x04;
05443                 /* id type */
05444                 names[i].encoded[idx++] = bType; 
05445                 /* str type */
05446                 names[i].encoded[idx++] = GetNameType(name, i);
05447             }
05448             /* second length */
05449             XMEMCPY(names[i].encoded + idx, secondLen, secondSz);
05450             idx += secondSz;
05451             /* str value */
05452             XMEMCPY(names[i].encoded + idx, nameStr, strLen);
05453             idx += strLen;
05454 
05455             totalBytes += idx;
05456             names[i].totalLen = idx;
05457             names[i].used = 1;
05458         }
05459         else
05460             names[i].used = 0;
05461     }
05462 
05463     /* header */
05464     idx = SetSequence(totalBytes, output);
05465     totalBytes += idx;
05466     if (totalBytes > ASN_NAME_MAX) {
05467 #ifdef CYASSL_SMALL_STACK
05468         XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05469 #endif
05470         return BUFFER_E;
05471     }
05472 
05473     for (i = 0; i < NAME_ENTRIES; i++) {
05474         if (names[i].used) {
05475             XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
05476             idx += names[i].totalLen;
05477         }
05478     }
05479 
05480 #ifdef CYASSL_SMALL_STACK
05481     XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05482 #endif
05483 
05484     return totalBytes;
05485 }
05486 
05487 /* encode info from cert into DER encoded format */
05488 static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
05489                       RNG* rng, const byte* ntruKey, word16 ntruSz)
05490 {
05491     int ret;
05492 
05493     (void)eccKey;
05494     (void)ntruKey;
05495     (void)ntruSz;
05496 
05497     /* init */
05498     XMEMSET(der, 0, sizeof(DerCert));
05499 
05500     /* version */
05501     der->versionSz = SetMyVersion(cert->version, der->version, TRUE);
05502 
05503     /* serial number */
05504     ret = RNG_GenerateBlock(rng, cert->serial, CTC_SERIAL_SIZE);
05505     if (ret != 0)
05506         return ret;
05507 
05508     cert->serial[0] = 0x01;   /* ensure positive */
05509     der->serialSz  = SetSerial(cert->serial, der->serial);
05510 
05511     /* signature algo */
05512     der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType, 0);
05513     if (der->sigAlgoSz == 0)
05514         return ALGO_ID_E;
05515 
05516     /* public key */
05517     if (cert->keyType == RSA_KEY) {
05518         if (rsaKey == NULL)
05519             return PUBLIC_KEY_E;
05520         der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey);
05521         if (der->publicKeySz <= 0)
05522             return PUBLIC_KEY_E;
05523     }
05524 
05525 #ifdef HAVE_ECC
05526     if (cert->keyType == ECC_KEY) {
05527         if (eccKey == NULL)
05528             return PUBLIC_KEY_E;
05529         der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey);
05530         if (der->publicKeySz <= 0)
05531             return PUBLIC_KEY_E;
05532     }
05533 #endif /* HAVE_ECC */
05534 
05535 #ifdef HAVE_NTRU
05536     if (cert->keyType == NTRU_KEY) {
05537         word32 rc;
05538         word16 encodedSz;
05539 
05540         rc  = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
05541                                                    ntruKey, &encodedSz, NULL);
05542         if (rc != NTRU_OK)
05543             return PUBLIC_KEY_E;
05544         if (encodedSz > MAX_PUBLIC_KEY_SZ)
05545             return PUBLIC_KEY_E;
05546 
05547         rc  = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
05548                                          ntruKey, &encodedSz, der->publicKey);
05549         if (rc != NTRU_OK)
05550             return PUBLIC_KEY_E;
05551 
05552         der->publicKeySz = encodedSz;
05553     }
05554 #endif /* HAVE_NTRU */
05555 
05556     der->validitySz = 0;
05557 #ifdef CYASSL_ALT_NAMES
05558     /* date validity copy ? */
05559     if (cert->beforeDateSz && cert->afterDateSz) {
05560         der->validitySz = CopyValidity(der->validity, cert);
05561         if (der->validitySz == 0)
05562             return DATE_E;
05563     }
05564 #endif
05565 
05566     /* date validity */
05567     if (der->validitySz == 0) {
05568         der->validitySz = SetValidity(der->validity, cert->daysValid);
05569         if (der->validitySz == 0)
05570             return DATE_E;
05571     }
05572 
05573     /* subject name */
05574     der->subjectSz = SetName(der->subject, &cert->subject);
05575     if (der->subjectSz == 0)
05576         return SUBJECT_E;
05577 
05578     /* issuer name */
05579     der->issuerSz = SetName(der->issuer, cert->selfSigned ?
05580              &cert->subject : &cert->issuer);
05581     if (der->issuerSz == 0)
05582         return ISSUER_E;
05583 
05584     /* CA */
05585     if (cert->isCA) {
05586         der->caSz = SetCa(der->ca);
05587         if (der->caSz == 0)
05588             return CA_TRUE_E;
05589     }
05590     else
05591         der->caSz = 0;
05592 
05593     /* extensions, just CA now */
05594     if (cert->isCA) {
05595         der->extensionsSz = SetExtensions(der->extensions,
05596                                           der->ca, der->caSz, TRUE);
05597         if (der->extensionsSz == 0)
05598             return EXTENSIONS_E;
05599     }
05600     else
05601         der->extensionsSz = 0;
05602 
05603 #ifdef CYASSL_ALT_NAMES
05604     if (der->extensionsSz == 0 && cert->altNamesSz) {
05605         der->extensionsSz = SetExtensions(der->extensions, cert->altNames,
05606                                           cert->altNamesSz, TRUE);
05607         if (der->extensionsSz == 0)
05608             return EXTENSIONS_E;
05609     }
05610 #endif
05611 
05612     der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
05613         der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz +
05614         der->extensionsSz;
05615 
05616     return 0;
05617 }
05618 
05619 
05620 /* write DER encoded cert to buffer, size already checked */
05621 static int WriteCertBody(DerCert* der, byte* buffer)
05622 {
05623     int idx;
05624 
05625     /* signed part header */
05626     idx = SetSequence(der->total, buffer);
05627     /* version */
05628     XMEMCPY(buffer + idx, der->version, der->versionSz);
05629     idx += der->versionSz;
05630     /* serial */
05631     XMEMCPY(buffer + idx, der->serial, der->serialSz);
05632     idx += der->serialSz;
05633     /* sig algo */
05634     XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz);
05635     idx += der->sigAlgoSz;
05636     /* issuer */
05637     XMEMCPY(buffer + idx, der->issuer, der->issuerSz);
05638     idx += der->issuerSz;
05639     /* validity */
05640     XMEMCPY(buffer + idx, der->validity, der->validitySz);
05641     idx += der->validitySz;
05642     /* subject */
05643     XMEMCPY(buffer + idx, der->subject, der->subjectSz);
05644     idx += der->subjectSz;
05645     /* public key */
05646     XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
05647     idx += der->publicKeySz;
05648     if (der->extensionsSz) {
05649         /* extensions */
05650         XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
05651                                                    sizeof(der->extensions)));
05652         idx += der->extensionsSz;
05653     }
05654 
05655     return idx;
05656 }
05657 
05658 
05659 /* Make RSA signature from buffer (sz), write to sig (sigSz) */
05660 static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz,
05661                          RsaKey* rsaKey, ecc_key* eccKey, RNG* rng,
05662                          int sigAlgoType)
05663 {
05664     int encSigSz, digestSz, typeH = 0, ret = 0;
05665     byte digest[SHA256_DIGEST_SIZE]; /* max size */
05666 #ifdef CYASSL_SMALL_STACK
05667     byte* encSig;
05668 #else
05669     byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ];
05670 #endif
05671 
05672     (void)digest;
05673     (void)digestSz;
05674     (void)encSig;
05675     (void)encSigSz;
05676     (void)typeH;
05677 
05678     (void)buffer;
05679     (void)sz;
05680     (void)sig;
05681     (void)sigSz;
05682     (void)rsaKey;
05683     (void)eccKey;
05684     (void)rng;
05685 
05686     switch (sigAlgoType) {
05687     #ifndef NO_MD5
05688         case CTC_MD5wRSA:
05689         if ((ret = Md5Hash(buffer, sz, digest)) == 0) {
05690             typeH    = MD5h;
05691             digestSz = MD5_DIGEST_SIZE;
05692         }
05693         break;
05694     #endif
05695     #ifndef NO_SHA
05696         case CTC_SHAwRSA:
05697         case CTC_SHAwECDSA:
05698         if ((ret = ShaHash(buffer, sz, digest)) == 0) {
05699             typeH    = SHAh;
05700             digestSz = SHA_DIGEST_SIZE;          
05701         }
05702         break;
05703     #endif
05704     #ifndef NO_SHA256
05705         case CTC_SHA256wRSA:
05706         case CTC_SHA256wECDSA:
05707         if ((ret = Sha256Hash(buffer, sz, digest)) == 0) {
05708             typeH    = SHA256h;
05709             digestSz = SHA256_DIGEST_SIZE;
05710         }
05711         break;
05712     #endif
05713         default:
05714             CYASSL_MSG("MakeSignautre called with unsupported type");
05715             ret = ALGO_ID_E;
05716     }
05717     
05718     if (ret != 0)
05719         return ret;
05720     
05721 #ifdef CYASSL_SMALL_STACK
05722     encSig = (byte*)XMALLOC(MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ,
05723                                                  NULL, DYNAMIC_TYPE_TMP_BUFFER);
05724     if (encSig == NULL)
05725         return MEMORY_E;
05726 #endif
05727     
05728     ret = ALGO_ID_E;
05729     
05730 #ifndef NO_RSA
05731     if (rsaKey) {
05732         /* signature */
05733         encSigSz = EncodeSignature(encSig, digest, digestSz, typeH);
05734         ret = RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng);
05735     }
05736 #endif
05737     
05738 #ifdef HAVE_ECC
05739     if (!rsaKey && eccKey) {
05740         word32 outSz = sigSz;
05741         ret = ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey);
05742 
05743         if (ret == 0)
05744             ret = outSz;
05745     }
05746 #endif
05747 
05748 #ifdef CYASSL_SMALL_STACK
05749     XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05750 #endif
05751 
05752     return ret;
05753 }
05754 
05755 
05756 /* add signature to end of buffer, size of buffer assumed checked, return
05757    new length */
05758 static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
05759                         int sigAlgoType)
05760 {
05761     byte seq[MAX_SEQ_SZ];
05762     int  idx = bodySz, seqSz;
05763 
05764     /* algo */
05765     idx += SetAlgoID(sigAlgoType, buffer + idx, sigType, 0);
05766     /* bit string */
05767     buffer[idx++] = ASN_BIT_STRING;
05768     /* length */
05769     idx += SetLength(sigSz + 1, buffer + idx);
05770     buffer[idx++] = 0;   /* trailing 0 */
05771     /* signature */
05772     XMEMCPY(buffer + idx, sig, sigSz);
05773     idx += sigSz;
05774 
05775     /* make room for overall header */
05776     seqSz = SetSequence(idx, seq);
05777     XMEMMOVE(buffer + seqSz, buffer, idx);
05778     XMEMCPY(buffer, seq, seqSz);
05779 
05780     return idx + seqSz;
05781 }
05782 
05783 
05784 /* Make an x509 Certificate v3 any key type from cert input, write to buffer */
05785 static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
05786                        RsaKey* rsaKey, ecc_key* eccKey, RNG* rng,
05787                        const byte* ntruKey, word16 ntruSz)
05788 {
05789     int ret;
05790 #ifdef CYASSL_SMALL_STACK
05791     DerCert* der;
05792 #else
05793     DerCert der[1];
05794 #endif
05795 
05796     cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY);
05797 
05798 #ifdef CYASSL_SMALL_STACK
05799     der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER);
05800     if (der == NULL)
05801         return MEMORY_E;
05802 #endif
05803 
05804     ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz);
05805 
05806     if (ret == 0) {
05807         if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
05808             ret = BUFFER_E;
05809         else
05810             ret = cert->bodySz = WriteCertBody(der, derBuffer);
05811     }
05812 
05813 #ifdef CYASSL_SMALL_STACK
05814     XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
05815 #endif
05816 
05817     return ret;
05818 }
05819 
05820 
05821 /* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
05822 int MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,
05823              ecc_key* eccKey, RNG* rng)
05824 {
05825     return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0);
05826 }
05827 
05828 
05829 #ifdef HAVE_NTRU
05830 
05831 int  MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
05832                   const byte* ntruKey, word16 keySz, RNG* rng)
05833 {
05834     return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz);
05835 }
05836 
05837 #endif /* HAVE_NTRU */
05838 
05839 
05840 #ifdef CYASSL_CERT_REQ
05841 
05842 static int SetReqAttrib(byte* output, char* pw, int extSz)
05843 {
05844     static const byte cpOid[] =
05845         { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
05846                          0x09, 0x07 };
05847     static const byte erOid[] =
05848         { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
05849                          0x09, 0x0e };
05850 
05851     int sz      = 0; /* overall size */
05852     int cpSz    = 0; /* Challenge Password section size */
05853     int cpSeqSz = 0;
05854     int cpSetSz = 0;
05855     int cpStrSz = 0;
05856     int pwSz    = 0;
05857     int erSz    = 0; /* Extension Request section size */
05858     int erSeqSz = 0;
05859     int erSetSz = 0;
05860     byte cpSeq[MAX_SEQ_SZ];
05861     byte cpSet[MAX_SET_SZ];
05862     byte cpStr[MAX_PRSTR_SZ];
05863     byte erSeq[MAX_SEQ_SZ];
05864     byte erSet[MAX_SET_SZ];
05865 
05866     output[0] = 0xa0;
05867     sz++;
05868 
05869     if (pw && pw[0]) {
05870         pwSz = (int)XSTRLEN(pw);
05871         cpStrSz = SetUTF8String(pwSz, cpStr);
05872         cpSetSz = SetSet(cpStrSz + pwSz, cpSet);
05873         cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq);
05874         cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz;
05875     }
05876 
05877     if (extSz) {
05878         erSetSz = SetSet(extSz, erSet);
05879         erSeqSz = SetSequence(erSetSz + sizeof(erOid) + extSz, erSeq);
05880         erSz = extSz + erSetSz + erSeqSz + sizeof(erOid);
05881     }
05882 
05883     /* Put the pieces together. */
05884     sz += SetLength(cpSz + erSz, &output[sz]);
05885 
05886     if (cpSz) {
05887         XMEMCPY(&output[sz], cpSeq, cpSeqSz);
05888         sz += cpSeqSz;
05889         XMEMCPY(&output[sz], cpOid, sizeof(cpOid));
05890         sz += sizeof(cpOid);
05891         XMEMCPY(&output[sz], cpSet, cpSetSz);
05892         sz += cpSetSz;
05893         XMEMCPY(&output[sz], cpStr, cpStrSz);
05894         sz += cpStrSz;
05895         XMEMCPY(&output[sz], pw, pwSz);
05896         sz += pwSz;
05897     }
05898 
05899     if (erSz) {
05900         XMEMCPY(&output[sz], erSeq, erSeqSz);
05901         sz += erSeqSz;
05902         XMEMCPY(&output[sz], erOid, sizeof(erOid));
05903         sz += sizeof(erOid);
05904         XMEMCPY(&output[sz], erSet, erSetSz);
05905         sz += erSetSz;
05906         /* The actual extension data will be tacked onto the output later. */
05907     }
05908 
05909     return sz;
05910 }
05911 
05912 
05913 /* encode info from cert into DER encoded format */
05914 static int EncodeCertReq(Cert* cert, DerCert* der,
05915                          RsaKey* rsaKey, ecc_key* eccKey)
05916 {
05917     (void)eccKey;
05918 
05919     /* init */
05920     XMEMSET(der, 0, sizeof(DerCert));
05921 
05922     /* version */
05923     der->versionSz = SetMyVersion(cert->version, der->version, FALSE);
05924 
05925     /* subject name */
05926     der->subjectSz = SetName(der->subject, &cert->subject);
05927     if (der->subjectSz == 0)
05928         return SUBJECT_E;
05929 
05930     /* public key */
05931     if (cert->keyType == RSA_KEY) {
05932         if (rsaKey == NULL)
05933             return PUBLIC_KEY_E;
05934         der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey);
05935         if (der->publicKeySz <= 0)
05936             return PUBLIC_KEY_E;
05937     }
05938 
05939 #ifdef HAVE_ECC
05940     if (cert->keyType == ECC_KEY) {
05941         if (eccKey == NULL)
05942             return PUBLIC_KEY_E;
05943         der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey);
05944         if (der->publicKeySz <= 0)
05945             return PUBLIC_KEY_E;
05946     }
05947 #endif /* HAVE_ECC */
05948 
05949     /* CA */
05950     if (cert->isCA) {
05951         der->caSz = SetCa(der->ca);
05952         if (der->caSz == 0)
05953             return CA_TRUE_E;
05954     }
05955     else
05956         der->caSz = 0;
05957 
05958     /* extensions, just CA now */
05959     if (cert->isCA) {
05960         der->extensionsSz = SetExtensions(der->extensions,
05961                                           der->ca, der->caSz, FALSE);
05962         if (der->extensionsSz == 0)
05963             return EXTENSIONS_E;
05964     }
05965     else
05966         der->extensionsSz = 0;
05967 
05968     der->attribSz = SetReqAttrib(der->attrib,
05969                                  cert->challengePw, der->extensionsSz);
05970     if (der->attribSz == 0)
05971         return REQ_ATTRIBUTE_E;
05972 
05973     der->total = der->versionSz + der->subjectSz + der->publicKeySz +
05974         der->extensionsSz + der->attribSz;
05975 
05976     return 0;
05977 }
05978 
05979 
05980 /* write DER encoded cert req to buffer, size already checked */
05981 static int WriteCertReqBody(DerCert* der, byte* buffer)
05982 {
05983     int idx;
05984 
05985     /* signed part header */
05986     idx = SetSequence(der->total, buffer);
05987     /* version */
05988     XMEMCPY(buffer + idx, der->version, der->versionSz);
05989     idx += der->versionSz;
05990     /* subject */
05991     XMEMCPY(buffer + idx, der->subject, der->subjectSz);
05992     idx += der->subjectSz;
05993     /* public key */
05994     XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
05995     idx += der->publicKeySz;
05996     /* attributes */
05997     XMEMCPY(buffer + idx, der->attrib, der->attribSz);
05998     idx += der->attribSz;
05999     /* extensions */
06000     if (der->extensionsSz) {
06001         XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
06002                                                    sizeof(der->extensions)));
06003         idx += der->extensionsSz;
06004     }
06005 
06006     return idx;
06007 }
06008 
06009 
06010 int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
06011                 RsaKey* rsaKey, ecc_key* eccKey)
06012 {
06013     int ret;
06014 #ifdef CYASSL_SMALL_STACK
06015     DerCert* der;
06016 #else
06017     DerCert der[1];
06018 #endif
06019 
06020     cert->keyType = eccKey ? ECC_KEY : RSA_KEY;
06021 
06022 #ifdef CYASSL_SMALL_STACK
06023     der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER);
06024     if (der == NULL)
06025         return MEMORY_E;
06026 #endif
06027 
06028     ret = EncodeCertReq(cert, der, rsaKey, eccKey);
06029 
06030     if (ret == 0) {
06031         if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
06032             ret = BUFFER_E;
06033         else
06034             ret = cert->bodySz = WriteCertReqBody(der, derBuffer);
06035     }
06036 
06037 #ifdef CYASSL_SMALL_STACK
06038     XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06039 #endif
06040 
06041     return ret;
06042 }
06043 
06044 #endif /* CYASSL_CERT_REQ */
06045 
06046 
06047 int SignCert(int requestSz, int sType, byte* buffer, word32 buffSz,
06048              RsaKey* rsaKey, ecc_key* eccKey, RNG* rng)
06049 {
06050     int sigSz;
06051 #ifdef CYASSL_SMALL_STACK
06052     byte* sig;
06053 #else
06054     byte sig[MAX_ENCODED_SIG_SZ];
06055 #endif
06056 
06057     if (requestSz < 0)
06058         return requestSz;
06059 
06060 #ifdef CYASSL_SMALL_STACK
06061     sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06062     if (sig == NULL)
06063         return MEMORY_E;
06064 #endif
06065 
06066     sigSz = MakeSignature(buffer, requestSz, sig, MAX_ENCODED_SIG_SZ, rsaKey,
06067                           eccKey, rng, sType);
06068 
06069     if (sigSz >= 0) {
06070         if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz)
06071             sigSz = BUFFER_E;
06072         else
06073             sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType);
06074     }
06075     
06076 #ifdef CYASSL_SMALL_STACK
06077     XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06078 #endif
06079 
06080     return sigSz;
06081 }
06082 
06083 
06084 int MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
06085 {
06086     int ret = MakeCert(cert, buffer, buffSz, key, NULL, rng);
06087 
06088     if (ret < 0)
06089         return ret;
06090 
06091     return SignCert(cert->bodySz, cert->sigType, buffer, buffSz, key, NULL,rng);
06092 }
06093 
06094 
06095 #ifdef CYASSL_ALT_NAMES 
06096 
06097 /* Set Alt Names from der cert, return 0 on success */
06098 static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
06099 {
06100     int ret;
06101 #ifdef CYASSL_SMALL_STACK
06102     DecodedCert* decoded;
06103 #else
06104     DecodedCert decoded[1];
06105 #endif
06106 
06107     if (derSz < 0)
06108         return derSz;
06109 
06110 #ifdef CYASSL_SMALL_STACK
06111     decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
06112                                                        DYNAMIC_TYPE_TMP_BUFFER);
06113     if (decoded == NULL)
06114         return MEMORY_E;
06115 #endif
06116     
06117     InitDecodedCert(decoded, (byte*)der, derSz, 0);
06118     ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
06119 
06120     if (ret < 0) {
06121         CYASSL_MSG("ParseCertRelative error");
06122     }
06123     else if (decoded->extensions) {
06124         byte   b;
06125         int    length;
06126         word32 maxExtensionsIdx;
06127 
06128         decoded->srcIdx = decoded->extensionsIdx;
06129         b = decoded->source[decoded->srcIdx++];
06130         
06131         if (b != ASN_EXTENSIONS) {
06132             ret = ASN_PARSE_E;
06133         }
06134         else if (GetLength(decoded->source, &decoded->srcIdx, &length,
06135                                                          decoded->maxIdx) < 0) {
06136             ret = ASN_PARSE_E;
06137         }
06138         else if (GetSequence(decoded->source, &decoded->srcIdx, &length,
06139                                                          decoded->maxIdx) < 0) {
06140             ret = ASN_PARSE_E;
06141         }
06142         else {
06143             maxExtensionsIdx = decoded->srcIdx + length;
06144 
06145             while (decoded->srcIdx < maxExtensionsIdx) {
06146                 word32 oid;
06147                 word32 startIdx = decoded->srcIdx;
06148                 word32 tmpIdx;
06149 
06150                 if (GetSequence(decoded->source, &decoded->srcIdx, &length,
06151                             decoded->maxIdx) < 0) {
06152                     ret = ASN_PARSE_E;
06153                     break;
06154                 }
06155 
06156                 tmpIdx = decoded->srcIdx;
06157                 decoded->srcIdx = startIdx;
06158 
06159                 if (GetAlgoId(decoded->source, &decoded->srcIdx, &oid,
06160                               decoded->maxIdx) < 0) {
06161                     ret = ASN_PARSE_E;
06162                     break;
06163                 }
06164 
06165                 if (oid == ALT_NAMES_OID) {
06166                     cert->altNamesSz = length + (tmpIdx - startIdx);
06167 
06168                     if (cert->altNamesSz < (int)sizeof(cert->altNames))
06169                         XMEMCPY(cert->altNames, &decoded->source[startIdx],
06170                                 cert->altNamesSz);
06171                     else {
06172                         cert->altNamesSz = 0;
06173                         CYASSL_MSG("AltNames extensions too big");
06174                         ret = ALT_NAME_E;
06175                         break;
06176                     }
06177                 }
06178                 decoded->srcIdx = tmpIdx + length;
06179             }
06180         }
06181     }
06182 
06183     FreeDecodedCert(decoded);
06184 #ifdef CYASSL_SMALL_STACK
06185     XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06186 #endif
06187 
06188     return ret < 0 ? ret : 0;
06189 }
06190 
06191 
06192 /* Set Dates from der cert, return 0 on success */
06193 static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
06194 {
06195     int ret;
06196 #ifdef CYASSL_SMALL_STACK
06197     DecodedCert* decoded;
06198 #else
06199     DecodedCert decoded[1];
06200 #endif
06201 
06202     CYASSL_ENTER("SetDatesFromCert");
06203     if (derSz < 0)
06204         return derSz;
06205     
06206 #ifdef CYASSL_SMALL_STACK
06207     decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
06208                                                        DYNAMIC_TYPE_TMP_BUFFER);
06209     if (decoded == NULL)
06210         return MEMORY_E;
06211 #endif
06212 
06213     InitDecodedCert(decoded, (byte*)der, derSz, 0);
06214     ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
06215 
06216     if (ret < 0) {
06217         CYASSL_MSG("ParseCertRelative error");
06218     }
06219     else if (decoded->beforeDate == NULL || decoded->afterDate == NULL) {
06220         CYASSL_MSG("Couldn't extract dates");
06221         ret = -1;
06222     }
06223     else if (decoded->beforeDateLen > MAX_DATE_SIZE || 
06224                                         decoded->afterDateLen > MAX_DATE_SIZE) {
06225         CYASSL_MSG("Bad date size");
06226         ret = -1;
06227     }
06228     else {
06229         XMEMCPY(cert->beforeDate, decoded->beforeDate, decoded->beforeDateLen);
06230         XMEMCPY(cert->afterDate,  decoded->afterDate,  decoded->afterDateLen);
06231 
06232         cert->beforeDateSz = decoded->beforeDateLen;
06233         cert->afterDateSz  = decoded->afterDateLen;
06234     }
06235 
06236     FreeDecodedCert(decoded);
06237 
06238 #ifdef CYASSL_SMALL_STACK
06239     XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06240 #endif
06241 
06242     return ret < 0 ? ret : 0;
06243 }
06244 
06245 
06246 #endif /* CYASSL_ALT_NAMES && !NO_RSA */
06247 
06248 
06249 /* Set cn name from der buffer, return 0 on success */
06250 static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
06251 {
06252     int ret, sz;
06253 #ifdef CYASSL_SMALL_STACK
06254     DecodedCert* decoded;
06255 #else
06256     DecodedCert decoded[1];
06257 #endif
06258 
06259     if (derSz < 0)
06260         return derSz;
06261 
06262 #ifdef CYASSL_SMALL_STACK
06263     decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
06264                                                        DYNAMIC_TYPE_TMP_BUFFER);
06265     if (decoded == NULL)
06266         return MEMORY_E;
06267 #endif
06268 
06269     InitDecodedCert(decoded, (byte*)der, derSz, 0);
06270     ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
06271 
06272     if (ret < 0) {
06273         CYASSL_MSG("ParseCertRelative error");
06274     }
06275     else {
06276         if (decoded->subjectCN) {
06277             sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen
06278                                                          : CTC_NAME_SIZE - 1;
06279             strncpy(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE);
06280             cn->commonName[sz] = 0;
06281             cn->commonNameEnc = decoded->subjectCNEnc;
06282         }
06283         if (decoded->subjectC) {
06284             sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen
06285                                                         : CTC_NAME_SIZE - 1;
06286             strncpy(cn->country, decoded->subjectC, CTC_NAME_SIZE);
06287             cn->country[sz] = 0;
06288             cn->countryEnc = decoded->subjectCEnc;
06289         }
06290         if (decoded->subjectST) {
06291             sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen
06292                                                          : CTC_NAME_SIZE - 1;
06293             strncpy(cn->state, decoded->subjectST, CTC_NAME_SIZE);
06294             cn->state[sz] = 0;
06295             cn->stateEnc = decoded->subjectSTEnc;
06296         }
06297         if (decoded->subjectL) {
06298             sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen
06299                                                         : CTC_NAME_SIZE - 1;
06300             strncpy(cn->locality, decoded->subjectL, CTC_NAME_SIZE);
06301             cn->locality[sz] = 0;
06302             cn->localityEnc = decoded->subjectLEnc;
06303         }
06304         if (decoded->subjectO) {
06305             sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen
06306                                                         : CTC_NAME_SIZE - 1;
06307             strncpy(cn->org, decoded->subjectO, CTC_NAME_SIZE);
06308             cn->org[sz] = 0;
06309             cn->orgEnc = decoded->subjectOEnc;
06310         }
06311         if (decoded->subjectOU) {
06312             sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen
06313                                                          : CTC_NAME_SIZE - 1;
06314             strncpy(cn->unit, decoded->subjectOU, CTC_NAME_SIZE);
06315             cn->unit[sz] = 0;
06316             cn->unitEnc = decoded->subjectOUEnc;
06317         }
06318         if (decoded->subjectSN) {
06319             sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen
06320                                                          : CTC_NAME_SIZE - 1;
06321             strncpy(cn->sur, decoded->subjectSN, CTC_NAME_SIZE);
06322             cn->sur[sz] = 0;
06323             cn->surEnc = decoded->subjectSNEnc;
06324         }
06325         if (decoded->subjectEmail) {
06326             sz = (decoded->subjectEmailLen < CTC_NAME_SIZE)
06327                ?  decoded->subjectEmailLen : CTC_NAME_SIZE - 1;
06328             strncpy(cn->email, decoded->subjectEmail, CTC_NAME_SIZE);
06329             cn->email[sz] = 0;
06330         }
06331     }
06332 
06333     FreeDecodedCert(decoded);
06334 
06335 #ifdef CYASSL_SMALL_STACK
06336     XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06337 #endif
06338 
06339     return ret < 0 ? ret : 0;
06340 }
06341 
06342 
06343 #ifndef NO_FILESYSTEM
06344 
06345 /* Set cert issuer from issuerFile in PEM */
06346 int SetIssuer(Cert* cert, const char* issuerFile)
06347 {
06348     int         ret;
06349     int         derSz;
06350     byte*       der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
06351 
06352     if (der == NULL) {
06353         CYASSL_MSG("SetIssuer OOF Problem");
06354         return MEMORY_E;
06355     }
06356     derSz = CyaSSL_PemCertToDer(issuerFile, der, EIGHTK_BUF);
06357     cert->selfSigned = 0;
06358     ret = SetNameFromCert(&cert->issuer, der, derSz);
06359     XFREE(der, NULL, DYNAMIC_TYPE_CERT);
06360 
06361     return ret;
06362 }
06363 
06364 
06365 /* Set cert subject from subjectFile in PEM */
06366 int SetSubject(Cert* cert, const char* subjectFile)
06367 {
06368     int         ret;
06369     int         derSz;
06370     byte*       der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
06371 
06372     if (der == NULL) {
06373         CYASSL_MSG("SetSubject OOF Problem");
06374         return MEMORY_E;
06375     }
06376     derSz = CyaSSL_PemCertToDer(subjectFile, der, EIGHTK_BUF);
06377     ret = SetNameFromCert(&cert->subject, der, derSz);
06378     XFREE(der, NULL, DYNAMIC_TYPE_CERT);
06379 
06380     return ret;
06381 }
06382 
06383 
06384 #ifdef CYASSL_ALT_NAMES
06385 
06386 /* Set atl names from file in PEM */
06387 int SetAltNames(Cert* cert, const char* file)
06388 {
06389     int         ret;
06390     int         derSz;
06391     byte*       der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
06392 
06393     if (der == NULL) {
06394         CYASSL_MSG("SetAltNames OOF Problem");
06395         return MEMORY_E;
06396     }
06397     derSz = CyaSSL_PemCertToDer(file, der, EIGHTK_BUF);
06398     ret = SetAltNamesFromCert(cert, der, derSz);
06399     XFREE(der, NULL, DYNAMIC_TYPE_CERT);
06400 
06401     return ret;
06402 }
06403 
06404 #endif /* CYASSL_ALT_NAMES */
06405 
06406 #endif /* NO_FILESYSTEM */
06407 
06408 /* Set cert issuer from DER buffer */
06409 int SetIssuerBuffer(Cert* cert, const byte* der, int derSz)
06410 {
06411     cert->selfSigned = 0;
06412     return SetNameFromCert(&cert->issuer, der, derSz);
06413 }
06414 
06415 
06416 /* Set cert subject from DER buffer */
06417 int SetSubjectBuffer(Cert* cert, const byte* der, int derSz)
06418 {
06419     return SetNameFromCert(&cert->subject, der, derSz);
06420 }
06421 
06422 
06423 #ifdef CYASSL_ALT_NAMES
06424 
06425 /* Set cert alt names from DER buffer */
06426 int SetAltNamesBuffer(Cert* cert, const byte* der, int derSz)
06427 {
06428     return SetAltNamesFromCert(cert, der, derSz);
06429 }
06430 
06431 /* Set cert dates from DER buffer */
06432 int SetDatesBuffer(Cert* cert, const byte* der, int derSz)
06433 {
06434     return SetDatesFromCert(cert, der, derSz);
06435 }
06436 
06437 #endif /* CYASSL_ALT_NAMES */
06438 
06439 #endif /* CYASSL_CERT_GEN */
06440 
06441 
06442 #ifdef HAVE_ECC
06443 
06444 /* Der Encode r & s ints into out, outLen is (in/out) size */
06445 int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
06446 {
06447     word32 idx = 0;
06448     word32 rSz;                           /* encoding size */
06449     word32 sSz;
06450     word32 headerSz = 4;   /* 2*ASN_TAG + 2*LEN(ENUM) */
06451 
06452     /* If the leading bit on the INTEGER is a 1, add a leading zero */
06453     int rLeadingZero = mp_leading_bit(r);
06454     int sLeadingZero = mp_leading_bit(s);
06455     int rLen = mp_unsigned_bin_size(r);   /* big int size */
06456     int sLen = mp_unsigned_bin_size(s);
06457     int err;
06458 
06459     if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero +
06460                    headerSz + 2))  /* SEQ_TAG + LEN(ENUM) */
06461         return BAD_FUNC_ARG;
06462 
06463     idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out);
06464 
06465     /* store r */
06466     out[idx++] = ASN_INTEGER;
06467     rSz = SetLength(rLen + rLeadingZero, &out[idx]);
06468     idx += rSz;
06469     if (rLeadingZero)
06470         out[idx++] = 0;
06471     err = mp_to_unsigned_bin(r, &out[idx]);
06472     if (err != MP_OKAY) return err;
06473     idx += rLen;
06474 
06475     /* store s */
06476     out[idx++] = ASN_INTEGER;
06477     sSz = SetLength(sLen + sLeadingZero, &out[idx]);
06478     idx += sSz;
06479     if (sLeadingZero)
06480         out[idx++] = 0;
06481     err = mp_to_unsigned_bin(s, &out[idx]);
06482     if (err != MP_OKAY) return err;
06483     idx += sLen;
06484 
06485     *outLen = idx;
06486 
06487     return 0;
06488 }
06489 
06490 
06491 /* Der Decode ECC-DSA Signautre, r & s stored as big ints */
06492 int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
06493 {
06494     word32 idx = 0;
06495     int    len = 0;
06496 
06497     if (GetSequence(sig, &idx, &len, sigLen) < 0)
06498         return ASN_ECC_KEY_E;
06499 
06500     if ((word32)len > (sigLen - idx))
06501         return ASN_ECC_KEY_E;
06502 
06503     if (GetInt(r, sig, &idx, sigLen) < 0)
06504         return ASN_ECC_KEY_E;
06505 
06506     if (GetInt(s, sig, &idx, sigLen) < 0)
06507         return ASN_ECC_KEY_E;
06508 
06509     return 0;
06510 }
06511 
06512 
06513 int EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
06514                         word32 inSz)
06515 {
06516     word32 oid = 0;
06517     int    version, length;
06518     int    privSz, pubSz;
06519     byte   b;
06520     int    ret = 0;
06521 #ifdef CYASSL_SMALL_STACK
06522     byte* priv;
06523     byte* pub;
06524 #else
06525     byte priv[ECC_MAXSIZE];
06526     byte pub[ECC_MAXSIZE * 2 + 1]; /* public key has two parts plus header */
06527 #endif
06528 
06529     if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
06530         return BAD_FUNC_ARG;
06531 
06532     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
06533         return ASN_PARSE_E;
06534 
06535     if (GetMyVersion(input, inOutIdx, &version) < 0)
06536         return ASN_PARSE_E;
06537 
06538     b = input[*inOutIdx];
06539     *inOutIdx += 1;
06540 
06541     /* priv type */
06542     if (b != 4 && b != 6 && b != 7) 
06543         return ASN_PARSE_E;
06544 
06545     if (GetLength(input, inOutIdx, &length, inSz) < 0)
06546         return ASN_PARSE_E;
06547 
06548     if (length > ECC_MAXSIZE)
06549         return BUFFER_E;
06550 
06551 #ifdef CYASSL_SMALL_STACK
06552     priv = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06553     if (priv == NULL)
06554         return MEMORY_E;
06555     
06556     pub = (byte*)XMALLOC(ECC_MAXSIZE * 2 + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06557     if (pub == NULL) {
06558         XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06559         return MEMORY_E;
06560     }
06561 #endif
06562 
06563     /* priv key */
06564     privSz = length;
06565     XMEMCPY(priv, &input[*inOutIdx], privSz);
06566     *inOutIdx += length;
06567 
06568     /* prefix 0, may have */
06569     b = input[*inOutIdx];
06570     if (b == ECC_PREFIX_0) {
06571         *inOutIdx += 1;
06572 
06573         if (GetLength(input, inOutIdx, &length, inSz) < 0)
06574             ret = ASN_PARSE_E;
06575         else {
06576             /* object id */
06577             b = input[*inOutIdx];
06578             *inOutIdx += 1;
06579 
06580             if (b != ASN_OBJECT_ID) {
06581                 ret = ASN_OBJECT_ID_E;
06582             }
06583             else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
06584                 ret = ASN_PARSE_E;
06585             }
06586             else {
06587                 while(length--) {
06588                     oid += input[*inOutIdx];
06589                     *inOutIdx += 1;
06590                 }
06591                 if (CheckCurve(oid) < 0)
06592                     ret = ECC_CURVE_OID_E;
06593             }
06594         }
06595     }
06596 
06597     if (ret == 0) {
06598         /* prefix 1 */
06599         b = input[*inOutIdx];
06600         *inOutIdx += 1;
06601 
06602         if (b != ECC_PREFIX_1) {
06603             ret = ASN_ECC_KEY_E;
06604         }
06605         else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
06606             ret = ASN_PARSE_E;
06607         }
06608         else {
06609             /* key header */
06610             b = input[*inOutIdx];
06611             *inOutIdx += 1;
06612             
06613             if (b != ASN_BIT_STRING) {
06614                 ret = ASN_BITSTR_E;
06615             }
06616             else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
06617                 ret = ASN_PARSE_E;
06618             }
06619             else {
06620                 b = input[*inOutIdx];
06621                 *inOutIdx += 1;
06622 
06623                 if (b != 0x00) {
06624                     ret = ASN_EXPECT_0_E;
06625                 }
06626                 else {
06627                     /* pub key */
06628                     pubSz = length - 1;  /* null prefix */
06629                     if (pubSz < (ECC_MAXSIZE*2 + 1)) {
06630                         XMEMCPY(pub, &input[*inOutIdx], pubSz);
06631                         *inOutIdx += length;
06632                         ret = ecc_import_private_key(priv, privSz, pub, pubSz,
06633                                                      key);
06634                     } else
06635                         ret = BUFFER_E;
06636                 }
06637             }
06638         }
06639     }
06640 
06641 #ifdef CYASSL_SMALL_STACK
06642     XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
06643     XFREE(pub,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
06644 #endif
06645 
06646     return ret;
06647 }
06648 
06649 
06650 #ifdef CYASSL_KEY_GEN
06651 
06652 /* Write a Private ecc key to DER format, length on success else < 0 */
06653 int EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
06654 {
06655     byte   curve[MAX_ALGO_SZ];
06656     byte   ver[MAX_VERSION_SZ];
06657     byte   seq[MAX_SEQ_SZ];
06658     int    ret;
06659     int    curveSz;
06660     int    verSz;
06661     int    privHdrSz  = ASN_ECC_HEADER_SZ;
06662     int    pubHdrSz   = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ;
06663     int    curveHdrSz = ASN_ECC_CONTEXT_SZ;
06664     word32 seqSz;
06665     word32 idx = 0;
06666     word32 pubSz = ECC_BUFSIZE;
06667     word32 privSz;
06668     word32 totalSz;
06669 
06670     if (key == NULL || output == NULL || inLen == 0)
06671         return BAD_FUNC_ARG;
06672 
06673     ret = ecc_export_x963(key, NULL, &pubSz);
06674     if (ret != LENGTH_ONLY_E) {
06675         return ret;
06676     }
06677     curveSz = SetCurve(key, curve);
06678     if (curveSz < 0) {
06679         return curveSz;
06680     }
06681 
06682     privSz = key->dp->size;
06683 
06684     verSz = SetMyVersion(1, ver, FALSE);
06685     if (verSz < 0) {
06686         return verSz;
06687     }
06688 
06689     totalSz = verSz + privSz + privHdrSz + curveSz + curveHdrSz +
06690               pubSz + pubHdrSz + 1;  /* plus null byte b4 public */
06691     seqSz = SetSequence(totalSz, seq);
06692     totalSz += seqSz;
06693 
06694     if (totalSz > inLen) {
06695         return BUFFER_E;
06696     }
06697 
06698     /* write it out */
06699     /* seq */
06700     XMEMCPY(output + idx, seq, seqSz);
06701     idx += seqSz;
06702 
06703    /* ver */
06704     XMEMCPY(output + idx, ver, verSz);
06705     idx += verSz;
06706 
06707     /* private */
06708     output[idx++] = ASN_OCTET_STRING;
06709     output[idx++] = (byte)privSz;
06710     ret = ecc_export_private_only(key, output + idx, &privSz);
06711     if (ret < 0) {
06712         return ret;
06713     }
06714     idx += privSz;
06715 
06716     /* curve */
06717     output[idx++] = ECC_PREFIX_0;
06718     output[idx++] = (byte)curveSz;
06719     XMEMCPY(output + idx, curve, curveSz);
06720     idx += curveSz;
06721 
06722     /* public */
06723     output[idx++] = ECC_PREFIX_1;
06724     output[idx++] = (byte)pubSz + ASN_ECC_CONTEXT_SZ + 1;  /* plus null byte */
06725     output[idx++] = ASN_BIT_STRING;
06726     output[idx++] = (byte)pubSz + 1;  /* plus null byte */
06727     output[idx++] = (byte)0;          /* null byte */
06728     ret = ecc_export_x963(key, output + idx, &pubSz);
06729     if (ret != 0) {
06730         return ret;
06731     }
06732     /* idx += pubSz if do more later */
06733 
06734     return totalSz;
06735 }
06736 
06737 #endif /* CYASSL_KEY_GEN */
06738 
06739 #endif  /* HAVE_ECC */
06740 
06741 
06742 #if defined(HAVE_OCSP) || defined(HAVE_CRL)
06743 
06744 /* Get raw Date only, no processing, 0 on success */
06745 static int GetBasicDate(const byte* source, word32* idx, byte* date,
06746                         byte* format, int maxIdx)
06747 {
06748     int    length;
06749 
06750     CYASSL_ENTER("GetBasicDate");
06751 
06752     *format = source[*idx];
06753     *idx += 1;
06754     if (*format != ASN_UTC_TIME && *format != ASN_GENERALIZED_TIME)
06755         return ASN_TIME_E;
06756 
06757     if (GetLength(source, idx, &length, maxIdx) < 0)
06758         return ASN_PARSE_E;
06759 
06760     if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
06761         return ASN_DATE_SZ_E;
06762 
06763     XMEMCPY(date, &source[*idx], length);
06764     *idx += length;
06765 
06766     return 0;
06767 }
06768 
06769 #endif
06770 
06771 
06772 #ifdef HAVE_OCSP
06773 
06774 static int GetEnumerated(const byte* input, word32* inOutIdx, int *value)
06775 {
06776     word32 idx = *inOutIdx;
06777     word32 len;
06778 
06779     CYASSL_ENTER("GetEnumerated");
06780 
06781     *value = 0;
06782 
06783     if (input[idx++] != ASN_ENUMERATED)
06784         return ASN_PARSE_E;
06785 
06786     len = input[idx++];
06787     if (len > 4)
06788         return ASN_PARSE_E;
06789 
06790     while (len--) {
06791         *value  = *value << 8 | input[idx++];
06792     }
06793 
06794     *inOutIdx = idx;
06795 
06796     return *value;
06797 }
06798 
06799 
06800 static int DecodeSingleResponse(byte* source,
06801                             word32* ioIndex, OcspResponse* resp, word32 size)
06802 {
06803     word32 idx = *ioIndex, prevIndex, oid;
06804     int length, wrapperSz;
06805     CertStatus* cs = resp->status;
06806 
06807     CYASSL_ENTER("DecodeSingleResponse");
06808 
06809     /* Outer wrapper of the SEQUENCE OF Single Responses. */
06810     if (GetSequence(source, &idx, &wrapperSz, size) < 0)
06811         return ASN_PARSE_E;
06812 
06813     prevIndex = idx;
06814 
06815     /* When making a request, we only request one status on one certificate
06816      * at a time. There should only be one SingleResponse */
06817 
06818     /* Wrapper around the Single Response */
06819     if (GetSequence(source, &idx, &length, size) < 0)
06820         return ASN_PARSE_E;
06821 
06822     /* Wrapper around the CertID */
06823     if (GetSequence(source, &idx, &length, size) < 0)
06824         return ASN_PARSE_E;
06825     /* Skip the hash algorithm */
06826     if (GetAlgoId(source, &idx, &oid, size) < 0)
06827         return ASN_PARSE_E;
06828     /* Save reference to the hash of CN */
06829     if (source[idx++] != ASN_OCTET_STRING)
06830         return ASN_PARSE_E;
06831     if (GetLength(source, &idx, &length, size) < 0)
06832         return ASN_PARSE_E;
06833     resp->issuerHash = source + idx;
06834     idx += length;
06835     /* Save reference to the hash of the issuer public key */
06836     if (source[idx++] != ASN_OCTET_STRING)
06837         return ASN_PARSE_E;
06838     if (GetLength(source, &idx, &length, size) < 0)
06839         return ASN_PARSE_E;
06840     resp->issuerKeyHash = source + idx;
06841     idx += length;
06842 
06843     /* Read the serial number, it is handled as a string, not as a 
06844      * proper number. Just XMEMCPY the data over, rather than load it
06845      * as an mp_int. */
06846     if (source[idx++] != ASN_INTEGER)
06847         return ASN_PARSE_E;
06848     if (GetLength(source, &idx, &length, size) < 0)
06849         return ASN_PARSE_E;
06850     if (length <= EXTERNAL_SERIAL_SIZE)
06851     {
06852         if (source[idx] == 0)
06853         {
06854             idx++;
06855             length--;
06856         }
06857         XMEMCPY(cs->serial, source + idx, length);
06858         cs->serialSz = length;
06859     }
06860     else
06861     {
06862         return ASN_GETINT_E;
06863     }
06864     idx += length;
06865 
06866     /* CertStatus */
06867     switch (source[idx++])
06868     {
06869         case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
06870             cs->status = CERT_GOOD;
06871             idx++;
06872             break;
06873         case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
06874             cs->status = CERT_REVOKED;
06875             if (GetLength(source, &idx, &length, size) < 0)
06876                 return ASN_PARSE_E;
06877             idx += length;
06878             break;
06879         case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN):
06880             cs->status = CERT_UNKNOWN;
06881             idx++;
06882             break;
06883         default:
06884             return ASN_PARSE_E;
06885     }
06886 
06887     if (GetBasicDate(source, &idx, cs->thisDate,
06888                                                 &cs->thisDateFormat, size) < 0)
06889         return ASN_PARSE_E;
06890     if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE))
06891         return ASN_BEFORE_DATE_E;
06892     
06893     /* The following items are optional. Only check for them if there is more
06894      * unprocessed data in the singleResponse wrapper. */
06895     
06896     if (((int)(idx - prevIndex) < wrapperSz) &&
06897         (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)))
06898     {
06899         idx++;
06900         if (GetLength(source, &idx, &length, size) < 0)
06901             return ASN_PARSE_E;
06902         if (GetBasicDate(source, &idx, cs->nextDate,
06903                                                 &cs->nextDateFormat, size) < 0)
06904             return ASN_PARSE_E;
06905     }
06906     if (((int)(idx - prevIndex) < wrapperSz) &&
06907         (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)))
06908     {
06909         idx++;
06910         if (GetLength(source, &idx, &length, size) < 0)
06911             return ASN_PARSE_E;
06912         idx += length;
06913     }
06914 
06915     *ioIndex = idx;
06916 
06917     return 0;
06918 }
06919 
06920 static int DecodeOcspRespExtensions(byte* source,
06921                             word32* ioIndex, OcspResponse* resp, word32 sz)
06922 {
06923     word32 idx = *ioIndex;
06924     int length;
06925     int ext_bound; /* boundary index for the sequence of extensions */
06926     word32 oid;
06927 
06928     CYASSL_ENTER("DecodeOcspRespExtensions");
06929 
06930     if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
06931         return ASN_PARSE_E;
06932 
06933     if (GetLength(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
06934 
06935     if (GetSequence(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
06936    
06937     ext_bound = idx + length;
06938 
06939     while (idx < (word32)ext_bound) {
06940         if (GetSequence(source, &idx, &length, sz) < 0) {
06941             CYASSL_MSG("\tfail: should be a SEQUENCE");
06942             return ASN_PARSE_E;
06943         }
06944 
06945         oid = 0;
06946         if (GetObjectId(source, &idx, &oid, sz) < 0) {
06947             CYASSL_MSG("\tfail: OBJECT ID");
06948             return ASN_PARSE_E;
06949         }
06950 
06951         /* check for critical flag */
06952         if (source[idx] == ASN_BOOLEAN) {
06953             CYASSL_MSG("\tfound optional critical flag, moving past");
06954             idx += (ASN_BOOL_SIZE + 1);
06955         }
06956 
06957         /* process the extension based on the OID */
06958         if (source[idx++] != ASN_OCTET_STRING) {
06959             CYASSL_MSG("\tfail: should be an OCTET STRING");
06960             return ASN_PARSE_E;
06961         }
06962 
06963         if (GetLength(source, &idx, &length, sz) < 0) {
06964             CYASSL_MSG("\tfail: extension data length");
06965             return ASN_PARSE_E;
06966         }
06967 
06968         if (oid == OCSP_NONCE_OID) {
06969             resp->nonce = source + idx;
06970             resp->nonceSz = length;
06971         }
06972 
06973         idx += length;
06974     }
06975 
06976     *ioIndex = idx;
06977     return 0;
06978 }
06979 
06980 
06981 static int DecodeResponseData(byte* source,
06982                             word32* ioIndex, OcspResponse* resp, word32 size)
06983 {
06984     word32 idx = *ioIndex, prev_idx;
06985     int length;
06986     int version;
06987     word32 responderId = 0;
06988 
06989     CYASSL_ENTER("DecodeResponseData");
06990 
06991     resp->response = source + idx;
06992     prev_idx = idx;
06993     if (GetSequence(source, &idx, &length, size) < 0)
06994         return ASN_PARSE_E;
06995     resp->responseSz = length + idx - prev_idx;
06996 
06997     /* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this
06998      * item isn't an EXPLICIT[0], then set version to zero and move
06999      * onto the next item.
07000      */
07001     if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
07002     {    
07003         idx += 2; /* Eat the value and length */
07004         if (GetMyVersion(source, &idx, &version) < 0)
07005             return ASN_PARSE_E;
07006     } else
07007         version = 0;
07008 
07009     responderId = source[idx++];
07010     if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
07011         (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
07012     {
07013         if (GetLength(source, &idx, &length, size) < 0)
07014             return ASN_PARSE_E;
07015         idx += length;
07016     }
07017     else
07018         return ASN_PARSE_E;
07019     
07020     /* save pointer to the producedAt time */
07021     if (GetBasicDate(source, &idx, resp->producedDate,
07022                                         &resp->producedDateFormat, size) < 0)
07023         return ASN_PARSE_E;
07024 
07025     if (DecodeSingleResponse(source, &idx, resp, size) < 0)
07026         return ASN_PARSE_E;
07027 
07028     if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
07029         return ASN_PARSE_E;
07030 
07031     *ioIndex = idx;
07032     return 0;
07033 }
07034 
07035 
07036 static int DecodeCerts(byte* source,
07037                             word32* ioIndex, OcspResponse* resp, word32 size)
07038 {
07039     word32 idx = *ioIndex;
07040 
07041     CYASSL_ENTER("DecodeCerts");
07042 
07043     if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
07044     {
07045         int length;
07046 
07047         if (GetLength(source, &idx, &length, size) < 0)
07048             return ASN_PARSE_E;
07049 
07050         if (GetSequence(source, &idx, &length, size) < 0)
07051             return ASN_PARSE_E;
07052 
07053         resp->cert = source + idx;
07054         resp->certSz = length;
07055 
07056         idx += length;
07057     }
07058     *ioIndex = idx;
07059     return 0;
07060 }
07061 
07062 static int DecodeBasicOcspResponse(byte* source,
07063                             word32* ioIndex, OcspResponse* resp, word32 size)
07064 {
07065     int length;
07066     word32 idx = *ioIndex;
07067     word32 end_index;
07068 
07069     CYASSL_ENTER("DecodeBasicOcspResponse");
07070 
07071     if (GetSequence(source, &idx, &length, size) < 0)
07072         return ASN_PARSE_E;
07073 
07074     if (idx + length > size)
07075         return ASN_INPUT_E;
07076     end_index = idx + length;
07077 
07078     if (DecodeResponseData(source, &idx, resp, size) < 0)
07079         return ASN_PARSE_E;
07080     
07081     /* Get the signature algorithm */
07082     if (GetAlgoId(source, &idx, &resp->sigOID, size) < 0)
07083         return ASN_PARSE_E;
07084 
07085     /* Obtain pointer to the start of the signature, and save the size */
07086     if (source[idx++] == ASN_BIT_STRING)
07087     {
07088         int sigLength = 0;
07089         if (GetLength(source, &idx, &sigLength, size) < 0)
07090             return ASN_PARSE_E;
07091         resp->sigSz = sigLength;
07092         resp->sig = source + idx;
07093         idx += sigLength;
07094     }
07095 
07096     /*
07097      * Check the length of the BasicOcspResponse against the current index to
07098      * see if there are certificates, they are optional.
07099      */
07100     if (idx < end_index)
07101     {
07102         DecodedCert cert;
07103         int ret;
07104 
07105         if (DecodeCerts(source, &idx, resp, size) < 0)
07106             return ASN_PARSE_E;
07107 
07108         InitDecodedCert(&cert, resp->cert, resp->certSz, 0);
07109         ret = ParseCertRelative(&cert, CA_TYPE, NO_VERIFY, 0);
07110         if (ret < 0)
07111             return ret;
07112 
07113         ret = ConfirmSignature(resp->response, resp->responseSz,
07114                             cert.publicKey, cert.pubKeySize, cert.keyOID,
07115                             resp->sig, resp->sigSz, resp->sigOID, NULL);
07116         FreeDecodedCert(&cert);
07117 
07118         if (ret == 0)
07119         {
07120             CYASSL_MSG("\tOCSP Confirm signature failed");
07121             return ASN_OCSP_CONFIRM_E;
07122         }
07123     }
07124 
07125     *ioIndex = idx;
07126     return 0;
07127 }
07128 
07129 
07130 void InitOcspResponse(OcspResponse* resp, CertStatus* status,
07131                                                     byte* source, word32 inSz)
07132 {
07133     CYASSL_ENTER("InitOcspResponse");
07134 
07135     resp->responseStatus = -1;
07136     resp->response = NULL;
07137     resp->responseSz = 0;
07138     resp->producedDateFormat = 0;
07139     resp->issuerHash = NULL;
07140     resp->issuerKeyHash = NULL;
07141     resp->sig = NULL;
07142     resp->sigSz = 0;
07143     resp->sigOID = 0;
07144     resp->status = status;
07145     resp->nonce = NULL;
07146     resp->nonceSz = 0;
07147     resp->source = source;
07148     resp->maxIdx = inSz;
07149 }
07150 
07151 
07152 int OcspResponseDecode(OcspResponse* resp)
07153 {
07154     int length = 0;
07155     word32 idx = 0;
07156     byte* source = resp->source;
07157     word32 size = resp->maxIdx;
07158     word32 oid;
07159 
07160     CYASSL_ENTER("OcspResponseDecode");
07161 
07162     /* peel the outer SEQUENCE wrapper */
07163     if (GetSequence(source, &idx, &length, size) < 0)
07164         return ASN_PARSE_E;
07165     
07166     /* First get the responseStatus, an ENUMERATED */
07167     if (GetEnumerated(source, &idx, &resp->responseStatus) < 0)
07168         return ASN_PARSE_E;
07169 
07170     if (resp->responseStatus != OCSP_SUCCESSFUL)
07171         return 0;
07172 
07173     /* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
07174     if (idx >= size)
07175         return ASN_INPUT_E;
07176     if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
07177         return ASN_PARSE_E;
07178     if (GetLength(source, &idx, &length, size) < 0)
07179         return ASN_PARSE_E;
07180 
07181     /* Get the responseBytes SEQUENCE */
07182     if (GetSequence(source, &idx, &length, size) < 0)
07183         return ASN_PARSE_E;
07184 
07185     /* Check ObjectID for the resposeBytes */
07186     if (GetObjectId(source, &idx, &oid, size) < 0)
07187         return ASN_PARSE_E;
07188     if (oid != OCSP_BASIC_OID)
07189         return ASN_PARSE_E;
07190     if (source[idx++] != ASN_OCTET_STRING)
07191         return ASN_PARSE_E;
07192 
07193     if (GetLength(source, &idx, &length, size) < 0)
07194         return ASN_PARSE_E;
07195 
07196     if (DecodeBasicOcspResponse(source, &idx, resp, size) < 0)
07197         return ASN_PARSE_E;
07198     
07199     return 0;
07200 }
07201 
07202 
07203 static word32 SetOcspReqExtensions(word32 extSz, byte* output,
07204                                             const byte* nonce, word32 nonceSz)
07205 {
07206     static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
07207                                        0x30, 0x01, 0x02 };
07208     byte seqArray[5][MAX_SEQ_SZ];
07209     word32 seqSz[5], totalSz;
07210 
07211     CYASSL_ENTER("SetOcspReqExtensions");
07212 
07213     if (nonce == NULL || nonceSz == 0) return 0;
07214     
07215     seqArray[0][0] = ASN_OCTET_STRING;
07216     seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]);
07217 
07218     seqArray[1][0] = ASN_OBJECT_ID;
07219     seqSz[1] = 1 + SetLength(sizeof(NonceObjId), &seqArray[1][1]);
07220 
07221     totalSz = seqSz[0] + seqSz[1] + nonceSz + (word32)sizeof(NonceObjId);
07222 
07223     seqSz[2] = SetSequence(totalSz, seqArray[2]);
07224     totalSz += seqSz[2];
07225 
07226     seqSz[3] = SetSequence(totalSz, seqArray[3]);
07227     totalSz += seqSz[3];
07228 
07229     seqArray[4][0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2);
07230     seqSz[4] = 1 + SetLength(totalSz, &seqArray[4][1]);
07231     totalSz += seqSz[4];
07232 
07233     if (totalSz < extSz)
07234     {
07235         totalSz = 0;
07236         XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
07237         totalSz += seqSz[4];
07238         XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
07239         totalSz += seqSz[3];
07240         XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
07241         totalSz += seqSz[2];
07242         XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
07243         totalSz += seqSz[1];
07244         XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
07245         totalSz += (word32)sizeof(NonceObjId);
07246         XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
07247         totalSz += seqSz[0];
07248         XMEMCPY(output + totalSz, nonce, nonceSz);
07249         totalSz += nonceSz;
07250     }
07251 
07252     return totalSz;
07253 }
07254 
07255 
07256 int EncodeOcspRequest(OcspRequest* req)
07257 {
07258     byte seqArray[5][MAX_SEQ_SZ];
07259     /* The ASN.1 of the OCSP Request is an onion of sequences */
07260     byte algoArray[MAX_ALGO_SZ];
07261     byte issuerArray[MAX_ENCODED_DIG_SZ];
07262     byte issuerKeyArray[MAX_ENCODED_DIG_SZ];
07263     byte snArray[MAX_SN_SZ];
07264     byte extArray[MAX_OCSP_EXT_SZ];
07265     byte* output = req->dest;
07266     word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz;
07267     int i;
07268 
07269     CYASSL_ENTER("EncodeOcspRequest");
07270 
07271     algoSz = SetAlgoID(SHAh, algoArray, hashType, 0);
07272 
07273     req->issuerHash = req->cert->issuerHash;
07274     issuerSz = SetDigest(req->cert->issuerHash, SHA_SIZE, issuerArray);
07275     
07276     req->issuerKeyHash = req->cert->issuerKeyHash;
07277     issuerKeySz = SetDigest(req->cert->issuerKeyHash, SHA_SIZE, issuerKeyArray);
07278 
07279     req->serial = req->cert->serial;
07280     req->serialSz = req->cert->serialSz;
07281     snSz = SetSerialNumber(req->cert->serial, req->cert->serialSz, snArray);
07282 
07283     extSz = 0;
07284     if (req->useNonce) {
07285         RNG rng;
07286         if (InitRng(&rng) != 0) {
07287             CYASSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
07288         } else {
07289             if (RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
07290                 CYASSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
07291             else {
07292                 req->nonceSz = MAX_OCSP_NONCE_SZ;
07293                 extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
07294                                                       req->nonce, req->nonceSz);
07295             }
07296         }
07297     }
07298 
07299     totalSz = algoSz + issuerSz + issuerKeySz + snSz;
07300 
07301     for (i = 4; i >= 0; i--) {
07302         seqSz[i] = SetSequence(totalSz, seqArray[i]);
07303         totalSz += seqSz[i];
07304         if (i == 2) totalSz += extSz;
07305     }
07306     totalSz = 0;
07307     for (i = 0; i < 5; i++) {
07308         XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
07309         totalSz += seqSz[i];
07310     }
07311     XMEMCPY(output + totalSz, algoArray, algoSz);
07312     totalSz += algoSz;
07313     XMEMCPY(output + totalSz, issuerArray, issuerSz);
07314     totalSz += issuerSz;
07315     XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz);
07316     totalSz += issuerKeySz;
07317     XMEMCPY(output + totalSz, snArray, snSz);
07318     totalSz += snSz;
07319     if (extSz != 0) {
07320         XMEMCPY(output + totalSz, extArray, extSz);
07321         totalSz += extSz;
07322     }
07323 
07324     return totalSz;
07325 }
07326 
07327 
07328 void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
07329                                                     byte* dest, word32 destSz)
07330 {
07331     CYASSL_ENTER("InitOcspRequest");
07332 
07333     req->cert = cert;
07334     req->useNonce = useNonce;
07335     req->nonceSz = 0;
07336     req->issuerHash = NULL;
07337     req->issuerKeyHash = NULL;
07338     req->serial = NULL;
07339     req->dest = dest;
07340     req->destSz = destSz;
07341 }
07342 
07343 
07344 int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
07345 {
07346     int cmp;
07347 
07348     CYASSL_ENTER("CompareOcspReqResp");
07349 
07350     if (req == NULL)
07351     {
07352         CYASSL_MSG("\tReq missing");
07353         return -1;
07354     }
07355 
07356     if (resp == NULL)
07357     {
07358         CYASSL_MSG("\tResp missing");
07359         return 1;
07360     }
07361 
07362     /* Nonces are not critical. The responder may not necessarily add
07363      * the nonce to the response. */
07364     if (req->useNonce && resp->nonceSz != 0) {
07365         cmp = req->nonceSz - resp->nonceSz;
07366         if (cmp != 0)
07367         {
07368             CYASSL_MSG("\tnonceSz mismatch");
07369             return cmp;
07370         }
07371     
07372         cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz);
07373         if (cmp != 0)
07374         {
07375             CYASSL_MSG("\tnonce mismatch");
07376             return cmp;
07377         }
07378     }
07379 
07380     cmp = XMEMCMP(req->issuerHash, resp->issuerHash, SHA_DIGEST_SIZE);
07381     if (cmp != 0)
07382     {
07383         CYASSL_MSG("\tissuerHash mismatch");
07384         return cmp;
07385     }
07386 
07387     cmp = XMEMCMP(req->issuerKeyHash, resp->issuerKeyHash, SHA_DIGEST_SIZE);
07388     if (cmp != 0)
07389     {
07390         CYASSL_MSG("\tissuerKeyHash mismatch");
07391         return cmp;
07392     }
07393 
07394     cmp = req->serialSz - resp->status->serialSz;
07395     if (cmp != 0)
07396     {
07397         CYASSL_MSG("\tserialSz mismatch");
07398         return cmp;
07399     }
07400 
07401     cmp = XMEMCMP(req->serial, resp->status->serial, req->serialSz);
07402     if (cmp != 0)
07403     {
07404         CYASSL_MSG("\tserial mismatch");
07405         return cmp;
07406     }
07407 
07408     return 0;
07409 }
07410 
07411 #endif
07412 
07413 
07414 /* store SHA1 hash of NAME */
07415 CYASSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
07416                              int maxIdx)
07417 {
07418     Sha    sha;
07419     int    length;  /* length of all distinguished names */
07420     int    ret = 0;
07421     word32 dummy;
07422 
07423     CYASSL_ENTER("GetNameHash");
07424 
07425     if (source[*idx] == ASN_OBJECT_ID) {
07426         CYASSL_MSG("Trying optional prefix...");
07427 
07428         if (GetLength(source, idx, &length, maxIdx) < 0)
07429             return ASN_PARSE_E;
07430 
07431         *idx += length;
07432         CYASSL_MSG("Got optional prefix");
07433     }
07434 
07435     /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
07436      * calculated over the entire DER encoding of the Name field, including
07437      * the tag and length. */
07438     dummy = *idx;
07439     if (GetSequence(source, idx, &length, maxIdx) < 0)
07440         return ASN_PARSE_E;
07441 
07442     ret = InitSha(&sha);
07443     if (ret != 0)
07444         return ret;
07445     ShaUpdate(&sha, source + dummy, length + *idx - dummy);
07446     ShaFinal(&sha, hash);
07447 
07448     *idx += length;
07449 
07450     return 0;
07451 }
07452 
07453 
07454 #ifdef HAVE_CRL
07455 
07456 /* initialize decoded CRL */
07457 void InitDecodedCRL(DecodedCRL* dcrl)
07458 {
07459     CYASSL_MSG("InitDecodedCRL");
07460 
07461     dcrl->certBegin    = 0;
07462     dcrl->sigIndex     = 0;
07463     dcrl->sigLength    = 0;
07464     dcrl->signatureOID = 0;
07465     dcrl->certs        = NULL;
07466     dcrl->totalCerts   = 0;
07467 }
07468 
07469 
07470 /* free decoded CRL resources */
07471 void FreeDecodedCRL(DecodedCRL* dcrl)
07472 {
07473     RevokedCert* tmp = dcrl->certs;
07474 
07475     CYASSL_MSG("FreeDecodedCRL");
07476 
07477     while(tmp) {
07478         RevokedCert* next = tmp->next;
07479         XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
07480         tmp = next;
07481     }
07482 }
07483 
07484 
07485 /* Get Revoked Cert list, 0 on success */
07486 static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
07487                       int maxIdx)
07488 {
07489     int    len;
07490     word32 end;
07491     byte   b;
07492     RevokedCert* rc;
07493 
07494     CYASSL_ENTER("GetRevoked");
07495 
07496     if (GetSequence(buff, idx, &len, maxIdx) < 0)
07497         return ASN_PARSE_E;
07498 
07499     end = *idx + len;
07500 
07501     /* get serial number */
07502     b = buff[*idx];
07503     *idx += 1;
07504 
07505     if (b != ASN_INTEGER) {
07506         CYASSL_MSG("Expecting Integer");
07507         return ASN_PARSE_E;
07508     }
07509 
07510     if (GetLength(buff, idx, &len, maxIdx) < 0)
07511         return ASN_PARSE_E;
07512 
07513     if (len > EXTERNAL_SERIAL_SIZE) {
07514         CYASSL_MSG("Serial Size too big");
07515         return ASN_PARSE_E;
07516     }
07517 
07518     rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), NULL, DYNAMIC_TYPE_CRL);
07519     if (rc == NULL) {
07520         CYASSL_MSG("Alloc Revoked Cert failed");
07521         return MEMORY_E;
07522     }
07523 
07524     XMEMCPY(rc->serialNumber, &buff[*idx], len);
07525     rc->serialSz = len;
07526 
07527     /* add to list */
07528     rc->next = dcrl->certs;
07529     dcrl->certs = rc;
07530     dcrl->totalCerts++;
07531 
07532     *idx += len;
07533 
07534     /* get date */
07535     b = buff[*idx];
07536     *idx += 1;
07537 
07538     if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) {
07539         CYASSL_MSG("Expecting Date");
07540         return ASN_PARSE_E;
07541     }
07542 
07543     if (GetLength(buff, idx, &len, maxIdx) < 0)
07544         return ASN_PARSE_E;
07545 
07546     /* skip for now */
07547     *idx += len;
07548 
07549     if (*idx != end)  /* skip extensions */
07550         *idx = end;
07551 
07552     return 0;
07553 }
07554 
07555 
07556 /* Get CRL Signature, 0 on success */
07557 static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
07558                             int maxIdx)
07559 {
07560     int    length;
07561     byte   b;
07562 
07563     CYASSL_ENTER("GetCRL_Signature");
07564 
07565     b = source[*idx];
07566     *idx += 1;
07567     if (b != ASN_BIT_STRING)
07568         return ASN_BITSTR_E;
07569 
07570     if (GetLength(source, idx, &length, maxIdx) < 0)
07571         return ASN_PARSE_E;
07572 
07573     dcrl->sigLength = length;
07574 
07575     b = source[*idx];
07576     *idx += 1;
07577     if (b != 0x00)
07578         return ASN_EXPECT_0_E;
07579 
07580     dcrl->sigLength--;
07581     dcrl->signature = (byte*)&source[*idx];
07582 
07583     *idx += dcrl->sigLength;
07584 
07585     return 0;
07586 }
07587 
07588 
07589 /* prase crl buffer into decoded state, 0 on success */
07590 int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
07591 {
07592     int     version, len;
07593     word32  oid, idx = 0;
07594     Signer* ca = NULL;
07595 
07596     CYASSL_MSG("ParseCRL");
07597 
07598     /* raw crl hash */
07599     /* hash here if needed for optimized comparisons
07600      * Sha     sha;
07601      * InitSha(&sha);
07602      * ShaUpdate(&sha, buff, sz);
07603      * ShaFinal(&sha, dcrl->crlHash); */
07604 
07605     if (GetSequence(buff, &idx, &len, sz) < 0)
07606         return ASN_PARSE_E;
07607 
07608     dcrl->certBegin = idx;
07609 
07610     if (GetSequence(buff, &idx, &len, sz) < 0)
07611         return ASN_PARSE_E;
07612     dcrl->sigIndex = len + idx;
07613 
07614     /* may have version */
07615     if (buff[idx] == ASN_INTEGER) {
07616         if (GetMyVersion(buff, &idx, &version) < 0)
07617             return ASN_PARSE_E;
07618     }
07619 
07620     if (GetAlgoId(buff, &idx, &oid, sz) < 0)
07621         return ASN_PARSE_E;
07622 
07623     if (GetNameHash(buff, &idx, dcrl->issuerHash, sz) < 0)
07624         return ASN_PARSE_E;
07625 
07626     if (GetBasicDate(buff, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
07627         return ASN_PARSE_E;
07628 
07629     if (GetBasicDate(buff, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
07630         return ASN_PARSE_E;
07631 
07632     if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
07633         CYASSL_MSG("CRL after date is no longer valid");
07634         return ASN_AFTER_DATE_E;
07635     }
07636 
07637     if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) {
07638         if (GetSequence(buff, &idx, &len, sz) < 0)
07639             return ASN_PARSE_E;
07640 
07641         len += idx;
07642 
07643         while (idx < (word32)len) {
07644             if (GetRevoked(buff, &idx, dcrl, sz) < 0)
07645                 return ASN_PARSE_E;
07646         }
07647     }
07648 
07649     if (idx != dcrl->sigIndex)
07650         idx = dcrl->sigIndex;   /* skip extensions */
07651 
07652     if (GetAlgoId(buff, &idx, &dcrl->signatureOID, sz) < 0)
07653         return ASN_PARSE_E;
07654 
07655     if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
07656         return ASN_PARSE_E;
07657 
07658     /* openssl doesn't add skid by default for CRLs cause firefox chokes
07659        we're not assuming it's available yet */
07660     #if !defined(NO_SKID) && defined(CRL_SKID_READY)
07661         if (dcrl->extAuthKeyIdSet)
07662             ca = GetCA(cm, dcrl->extAuthKeyId);
07663         if (ca == NULL)
07664             ca = GetCAByName(cm, dcrl->issuerHash);
07665     #else /* NO_SKID */
07666         ca = GetCA(cm, dcrl->issuerHash);
07667     #endif /* NO_SKID */
07668     CYASSL_MSG("About to verify CRL signature");
07669 
07670     if (ca) {
07671         CYASSL_MSG("Found CRL issuer CA");
07672         /* try to confirm/verify signature */
07673         #ifndef IGNORE_KEY_EXTENSIONS
07674             if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) {
07675                 CYASSL_MSG("CA cannot sign CRLs");
07676                 return ASN_CRL_NO_SIGNER_E;
07677             }
07678         #endif /* IGNORE_KEY_EXTENSIONS */
07679         if (!ConfirmSignature(buff + dcrl->certBegin,
07680                 dcrl->sigIndex - dcrl->certBegin,
07681                 ca->publicKey, ca->pubKeySize, ca->keyOID,
07682                 dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) {
07683             CYASSL_MSG("CRL Confirm signature failed");
07684             return ASN_CRL_CONFIRM_E;
07685         }
07686     }
07687     else {
07688         CYASSL_MSG("Did NOT find CRL issuer CA");
07689         return ASN_CRL_NO_SIGNER_E;
07690     }
07691 
07692     return 0;
07693 }
07694 
07695 #endif /* HAVE_CRL */
07696 #endif
07697 
07698 #ifdef CYASSL_SEP
07699 
07700 
07701 
07702 #endif /* CYASSL_SEP */
07703