summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c')
-rw-r--r--FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c16530
1 files changed, 13130 insertions, 3400 deletions
diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c
index e3d9ff44b..c4e60043f 100644
--- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c
+++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/asn.c
@@ -1,8 +1,8 @@
/* asn.c
*
- * Copyright (C) 2006-2015 wolfSSL Inc.
+ * Copyright (C) 2006-2020 wolfSSL Inc.
*
- * This file is part of wolfSSL. (formerly known as CyaSSL)
+ * This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,21 +16,47 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
-#ifndef NO_ASN
+/*
+ASN Options:
+ * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC
+ or wishing to save space.
+ * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks.
+ * ASN_DUMP_OID: Allows dump of OID information for debugging.
+ * RSA_DECODE_EXTRA: Decodes extra information in RSA public key.
+ * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName.
+ * WOLFSSL_NO_ASN_STRICT: Disable strict RFC compliance checks to
+ restore 3.13.0 behavior.
+ * WOLFSSL_NO_OCSP_OPTIONAL_CERTS: Skip optional OCSP certs (responder issuer
+ must still be trusted)
+ * WOLFSSL_NO_TRUSTED_CERTS_VERIFY: Workaround for situation where entire cert
+ chain is not loaded. This only matches on subject and public key and
+ does not perform a PKI validation, so it is not a secure solution.
+ Only enabled for OCSP.
+ * WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to
+ disable checking of OCSP subject hash with issuer hash.
+ * WOLFSSL_SMALL_CERT_VERIFY: Verify the certificate signature without using
+ DecodedCert. Doubles up on some code but allows smaller dynamic memory
+ usage.
+ * WOLFSSL_NO_OCSP_DATE_CHECK: Disable date checks for OCSP responses. This
+ may be required when the system's real-time clock is not very accurate.
+ It is recommended to enforce the nonce check instead if possible.
+ * WOLFSSL_FORCE_OCSP_NONCE_CHECK: Require nonces to be available in OCSP
+ responses. The nonces are optional and may not be supported by all
+ responders. If it can be ensured that the used responder sends nonces this
+ option may improve security.
+*/
-#ifdef HAVE_RTP_SYS
- #include "os.h" /* dc_rtc_api needs */
- #include "dc_rtc_api.h" /* to get current time */
-#endif
+#ifndef NO_ASN
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/coding.h>
@@ -39,17 +65,25 @@
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/pwdbased.h>
#include <wolfssl/wolfcrypt/des3.h>
+#include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/wc_encrypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/random.h>
-
+#include <wolfssl/wolfcrypt/hash.h>
+#ifdef NO_INLINE
+ #include <wolfssl/wolfcrypt/misc.h>
+#else
+ #define WOLFSSL_MISC_INCLUDED
+ #include <wolfcrypt/src/misc.c>
+#endif
#ifndef NO_RC4
#include <wolfssl/wolfcrypt/arc4.h>
#endif
#ifdef HAVE_NTRU
- #include "ntru_crypto.h"
+ #include "libntruencrypt/ntru_crypto.h"
#endif
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
@@ -64,478 +98,640 @@
#include <wolfssl/wolfcrypt/ecc.h>
#endif
-#ifdef WOLFSSL_DEBUG_ENCODING
- #ifdef FREESCALE_MQX
- #include <fio.h>
- #else
- #include <stdio.h>
- #endif
+#ifdef HAVE_ED25519
+ #include <wolfssl/wolfcrypt/ed25519.h>
#endif
-#ifdef _MSC_VER
- /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
- #pragma warning(disable: 4996)
+#ifdef HAVE_ED448
+ #include <wolfssl/wolfcrypt/ed448.h>
#endif
-
-#ifndef TRUE
- #define TRUE 1
+#ifndef NO_RSA
+ #include <wolfssl/wolfcrypt/rsa.h>
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
+extern int wc_InitRsaHw(RsaKey* key);
#endif
-#ifndef FALSE
- #define FALSE 0
#endif
+#ifdef WOLF_CRYPTO_CB
+ #include <wolfssl/wolfcrypt/cryptocb.h>
+#endif
-#ifdef HAVE_RTP_SYS
- /* uses parital <time.h> structures */
- #define XTIME(tl) (0)
- #define XGMTIME(c, t) my_gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(MICRIUM)
- #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
- #define XVALIDATE_DATE(d,f,t) NetSecure_ValidateDateHandler((d),(f),(t))
- #else
- #define XVALIDATE_DATE(d, f, t) (0)
- #endif
- #define NO_TIME_H
- /* since Micrium not defining XTIME or XGMTIME, CERT_GEN not available */
-#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
- #include <time.h>
- #define XTIME(t1) pic32_time((t1))
- #define XGMTIME(c, t) gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(FREESCALE_MQX)
- #define XTIME(t1) mqx_time((t1))
- #define XGMTIME(c, t) mqx_gmtime((c), (t))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(WOLFSSL_MDK_ARM)
- #if defined(WOLFSSL_MDK5)
- #include "cmsis_os.h"
- #else
- #include <rtl.h>
- #endif
- #undef RNG
- #include "wolfssl_MDK_ARM.h"
- #undef RNG
- #define RNG wolfSSL_RNG /*for avoiding name conflict in "stm32f2xx.h" */
- #define XTIME(tl) (0)
- #define XGMTIME(c, t) wolfssl_MDK_gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-#elif defined(USER_TIME)
- /* user time, and gmtime compatible functions, there is a gmtime
- implementation here that WINCE uses, so really just need some ticks
- since the EPOCH
- */
-
- struct tm {
- int tm_sec; /* seconds after the minute [0-60] */
- int tm_min; /* minutes after the hour [0-59] */
- int tm_hour; /* hours since midnight [0-23] */
- int tm_mday; /* day of the month [1-31] */
- int tm_mon; /* months since January [0-11] */
- int tm_year; /* years since 1900 */
- int tm_wday; /* days since Sunday [0-6] */
- int tm_yday; /* days since January 1 [0-365] */
- int tm_isdst; /* Daylight Savings Time flag */
- long tm_gmtoff; /* offset from CUT in seconds */
- char *tm_zone; /* timezone abbreviation */
- };
- typedef long time_t;
-
- /* forward declaration */
- struct tm* gmtime(const time_t* timer);
- extern time_t XTIME(time_t * timer);
-
- #define XGMTIME(c, t) gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
-
- #ifdef STACK_TRAP
- /* for stack trap tracking, don't call os gmtime on OS X/linux,
- uses a lot of stack spce */
- extern time_t time(time_t * timer);
- #define XTIME(tl) time((tl))
- #endif /* STACK_TRAP */
-
-#elif defined(TIME_OVERRIDES)
- /* user would like to override time() and gmtime() functionality */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ #include <wolfssl/openssl/objects.h>
+#endif
- #ifndef HAVE_TIME_T_TYPE
- typedef long time_t;
- #endif
- extern time_t XTIME(time_t * timer);
-
- #ifndef HAVE_TM_TYPE
- struct tm {
- int tm_sec; /* seconds after the minute [0-60] */
- int tm_min; /* minutes after the hour [0-59] */
- int tm_hour; /* hours since midnight [0-23] */
- int tm_mday; /* day of the month [1-31] */
- int tm_mon; /* months since January [0-11] */
- int tm_year; /* years since 1900 */
- int tm_wday; /* days since Sunday [0-6] */
- int tm_yday; /* days since January 1 [0-365] */
- int tm_isdst; /* Daylight Savings Time flag */
- long tm_gmtoff; /* offset from CUT in seconds */
- char *tm_zone; /* timezone abbreviation */
- };
- #endif
- extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp);
+#ifdef _MSC_VER
+ /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */
+ #pragma warning(disable: 4996)
+#endif
- #ifndef HAVE_VALIDATE_DATE
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
+#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
+
+#if defined(HAVE_SELFTEST) || ( !defined(NO_SKID) && \
+ ( !defined(HAVE_FIPS) || \
+ !defined(HAVE_FIPS_VERSION) ))
+ #ifndef WOLFSSL_AES_KEY_SIZE_ENUM
+ #define WOLFSSL_AES_KEY_SIZE_ENUM
+ enum Asn_Misc {
+ AES_IV_SIZE = 16,
+ AES_128_KEY_SIZE = 16,
+ AES_192_KEY_SIZE = 24,
+ AES_256_KEY_SIZE = 32
+ };
#endif
-#else
- /* default */
- /* uses complete <time.h> facility */
- #include <time.h>
- #define XTIME(tl) time((tl))
- #define XGMTIME(c, t) gmtime((c))
- #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t))
#endif
-
-
-#ifdef _WIN32_WCE
-/* no time() or gmtime() even though in time.h header?? */
-
-#include <windows.h>
-
-
-time_t time(time_t* timer)
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+void tsip_inform_key_position(const word32 key_n_start,
+ const word32 key_n_len, const word32 key_e_start,
+ const word32 key_e_len);
+int tsip_tls_CertVerify(const byte *cert, word32 certSz,
+ const byte *signature, word32 sigSz,
+ word32 key_n_start, word32 key_n_len,
+ word32 key_e_start, word32 key_e_len,
+ byte *tsip_encRsaKeyIdx);
+#endif
+int GetLength(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- SYSTEMTIME sysTime;
- FILETIME fTime;
- ULARGE_INTEGER intTime;
- time_t localTime;
-
- if (timer == NULL)
- timer = &localTime;
-
- GetSystemTime(&sysTime);
- SystemTimeToFileTime(&sysTime, &fTime);
-
- XMEMCPY(&intTime, &fTime, sizeof(FILETIME));
- /* subtract EPOCH */
- intTime.QuadPart -= 0x19db1ded53e8000;
- /* to secs */
- intTime.QuadPart /= 10000000;
- *timer = (time_t)intTime.QuadPart;
-
- return *timer;
+ return GetLength_ex(input, inOutIdx, len, maxIdx, 1);
}
-#endif /* _WIN32_WCE */
-#if defined( _WIN32_WCE ) || defined( USER_TIME )
-struct tm* gmtime(const time_t* timer)
+/* give option to check length value found against index. 1 to check 0 to not */
+int GetLength_ex(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
{
- #define YEAR0 1900
- #define EPOCH_YEAR 1970
- #define SECS_DAY (24L * 60L * 60L)
- #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) %400)))
- #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
+ int length = 0;
+ word32 idx = *inOutIdx;
+ byte b;
- static const int _ytab[2][12] =
- {
- {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
- {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
- };
+ *len = 0; /* default length */
- static struct tm st_time;
- struct tm* ret = &st_time;
- time_t secs = *timer;
- unsigned long dayclock, dayno;
- int year = EPOCH_YEAR;
+ if ((idx + 1) > maxIdx) { /* for first read */
+ WOLFSSL_MSG("GetLength bad index on input");
+ return BUFFER_E;
+ }
- dayclock = (unsigned long)secs % SECS_DAY;
- dayno = (unsigned long)secs / SECS_DAY;
+ b = input[idx++];
+ if (b >= ASN_LONG_LENGTH) {
+ word32 bytes = b & 0x7F;
- ret->tm_sec = (int) dayclock % 60;
- ret->tm_min = (int)(dayclock % 3600) / 60;
- ret->tm_hour = (int) dayclock / 3600;
- ret->tm_wday = (int) (dayno + 4) % 7; /* day 0 a Thursday */
+ if ((idx + bytes) > maxIdx) { /* for reading bytes */
+ WOLFSSL_MSG("GetLength bad long length");
+ return BUFFER_E;
+ }
- while(dayno >= (unsigned long)YEARSIZE(year)) {
- dayno -= YEARSIZE(year);
- year++;
+ if (bytes > sizeof(length)) {
+ return ASN_PARSE_E;
+ }
+ while (bytes--) {
+ b = input[idx++];
+ length = (length << 8) | b;
+ }
+ if (length < 0) {
+ return ASN_PARSE_E;
+ }
}
+ else
+ length = b;
- ret->tm_year = year - YEAR0;
- ret->tm_yday = (int)dayno;
- ret->tm_mon = 0;
-
- while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) {
- dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon];
- ret->tm_mon++;
+ if (check && (idx + length) > maxIdx) { /* for user of length */
+ WOLFSSL_MSG("GetLength value exceeds buffer length");
+ return BUFFER_E;
}
- ret->tm_mday = (int)++dayno;
- ret->tm_isdst = 0;
+ *inOutIdx = idx;
+ if (length > 0)
+ *len = length;
- return ret;
+ return length;
}
-#endif /* _WIN32_WCE || USER_TIME */
+/* input : buffer to read from
+ * inOutIdx : index to start reading from, gets advanced by 1 if successful
+ * maxIdx : maximum index value
+ * tag : ASN tag value found
+ *
+ * returns 0 on success
+ */
+int GetASNTag(const byte* input, word32* inOutIdx, byte* tag, word32 maxIdx)
+{
+ word32 idx;
-#ifdef HAVE_RTP_SYS
+ if (tag == NULL || inOutIdx == NULL || input == NULL) {
+ return BAD_FUNC_ARG;
+ }
-#define YEAR0 1900
+ idx = *inOutIdx;
+ if (idx + ASN_TAG_SZ > maxIdx) {
+ WOLFSSL_MSG("Buffer too small for ASN tag");
+ return BUFFER_E;
+ }
-struct tm* my_gmtime(const time_t* timer) /* has a gmtime() but hangs */
-{
- static struct tm st_time;
- struct tm* ret = &st_time;
+ *tag = input[idx];
+ *inOutIdx = idx + ASN_TAG_SZ;
+ return 0;
+}
- DC_RTC_CALENDAR cal;
- dc_rtc_time_get(&cal, TRUE);
- ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */
- ret->tm_mon = cal.month - 1; /* gm starts at 0 */
- ret->tm_mday = cal.day;
- ret->tm_hour = cal.hour;
- ret->tm_min = cal.minute;
- ret->tm_sec = cal.second;
+static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ word32 idx = *inOutIdx;
+ byte tagFound;
+ int length;
- return ret;
-}
+ if (GetASNTag(input, &idx, &tagFound, maxIdx) != 0)
+ return ASN_PARSE_E;
-#endif /* HAVE_RTP_SYS */
+ if (tagFound != tag)
+ return ASN_PARSE_E;
+
+ if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
+ return ASN_PARSE_E;
+ *len = length;
+ *inOutIdx = idx;
+ return length;
+}
-#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
-/*
- * time() is just a stub in Microchip libraries. We need our own
- * implementation. Use SNTP client to get seconds since epoch.
+/* Get the DER/BER encoding of an ASN.1 header.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * tag ASN.1 tag value expected in header.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the expected tag is not found or length is invalid.
+ * Otherwise, the number of bytes in the ASN.1 data.
*/
-time_t pic32_time(time_t* timer)
+static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
-#ifdef MICROCHIP_TCPIP_V5
- DWORD sec = 0;
-#else
- uint32_t sec = 0;
-#endif
- time_t localTime;
-
- if (timer == NULL)
- timer = &localTime;
+ return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1);
+}
-#ifdef MICROCHIP_MPLAB_HARMONY
- sec = TCPIP_SNTP_UTCSecondsGet();
-#else
- sec = SNTPGetUTCSeconds();
-#endif
- *timer = (time_t) sec;
+static int GetHeader(const byte* input, byte* tag, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ word32 idx = *inOutIdx;
+ int length;
- return *timer;
-}
+ if ((idx + 1) > maxIdx)
+ return BUFFER_E;
-#endif /* MICROCHIP_TCPIP */
+ *tag = input[idx++];
+ if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0)
+ return ASN_PARSE_E;
-#ifdef FREESCALE_MQX
+ *len = length;
+ *inOutIdx = idx;
+ return length;
+}
-time_t mqx_time(time_t* timer)
+int GetSequence(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- time_t localTime;
- TIME_STRUCT time_s;
-
- if (timer == NULL)
- timer = &localTime;
+ return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx);
+}
- _time_get(&time_s);
- *timer = (time_t) time_s.SECONDS;
- return *timer;
+int GetSequence_ex(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ return GetASNHeader_ex(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx, check);
}
-/* CodeWarrior GCC toolchain only has gmtime_r(), no gmtime() */
-struct tm* mqx_gmtime(const time_t* clock, struct tm* tmpTime)
+
+int GetSet(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- return gmtime_r(clock, tmpTime);
+ return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx);
}
-#endif /* FREESCALE_MQX */
-#ifdef WOLFSSL_TIRTOS
+int GetSet_ex(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int check)
+{
+ return GetASNHeader_ex(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len,
+ maxIdx, check);
+}
-time_t XTIME(time_t * timer)
+/* Get the DER/BER encoded ASN.1 NULL element.
+ * Ensure that the all fields are as expected and move index past the element.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_TAG_NULL_E when the NULL tag is not found.
+ * ASN_EXPECT_0_E when the length is not zero.
+ * Otherwise, 0 to indicate success.
+ */
+static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx)
{
- time_t sec = 0;
+ word32 idx = *inOutIdx;
+ byte b;
+
+ if ((idx + 2) > maxIdx)
+ return BUFFER_E;
- sec = (time_t) Seconds_get();
+ b = input[idx++];
+ if (b != ASN_TAG_NULL)
+ return ASN_TAG_NULL_E;
- if (timer != NULL)
- *timer = sec;
+ if (input[idx++] != 0)
+ return ASN_EXPECT_0_E;
- return sec;
+ *inOutIdx = idx;
+ return 0;
}
-#endif /* WOLFSSL_TIRTOS */
-
-static INLINE word32 btoi(byte b)
+/* Set the DER/BER encoding of the ASN.1 NULL element.
+ *
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetASNNull(byte* output)
{
- return b - 0x30;
-}
+ output[0] = ASN_TAG_NULL;
+ output[1] = 0;
+ return 2;
+}
-/* two byte date/time, add to value */
-static INLINE void GetTime(int* value, const byte* date, int* idx)
+/* Get the DER/BER encoding of an ASN.1 BOOLEAN.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1.
+ * Otherwise, 0 to indicate the value was false and 1 to indicate true.
+ */
+static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx)
{
- int i = *idx;
+ word32 idx = *inOutIdx;
+ byte b;
- *value += btoi(date[i++]) * 10;
- *value += btoi(date[i++]);
+ if ((idx + 3) > maxIdx)
+ return BUFFER_E;
- *idx = i;
+ b = input[idx++];
+ if (b != ASN_BOOLEAN)
+ return ASN_PARSE_E;
+
+ if (input[idx++] != 1)
+ return ASN_PARSE_E;
+
+ b = input[idx++] != 0;
+
+ *inOutIdx = idx;
+ return b;
}
+#ifdef ASN1_SET_BOOLEAN
+/* Set the DER/BER encoding of the ASN.1 NULL element.
+ * Note: Function not required as yet.
+ *
+ * val Boolean value to encode.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetBoolean(int val, byte* output)
+{
+ output[0] = ASN_BOOLEAN;
+ output[1] = 1;
+ output[2] = val ? -1 : 0;
-#if defined(MICRIUM)
+ return 3;
+}
+#endif
-CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format,
- CPU_INT08U dateType)
+/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the OCTET_STRING tag is not found or length is
+ * invalid.
+ * Otherwise, the number of bytes in the ASN.1 data.
+ */
+int GetOctetString(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
{
- CPU_BOOLEAN rtn_code;
- CPU_INT32S i;
- CPU_INT32S val;
- CPU_INT16U year;
- CPU_INT08U month;
- CPU_INT16U day;
- CPU_INT08U hour;
- CPU_INT08U min;
- CPU_INT08U sec;
+ return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx);
+}
- i = 0;
- year = 0u;
+/* Get the DER/BER encoding of an ASN.1 INTEGER header.
+ * Removes the leading zero byte when found.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data (excluding any leading zero).
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the INTEGER tag is not found, length is invalid,
+ * or invalid use of or missing leading zero.
+ * Otherwise, 0 to indicate success.
+ */
+static int GetASNInt(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ int ret;
- if (format == ASN_UTC_TIME) {
- if (btoi(date[0]) >= 5)
- year = 1900;
- else
- year = 2000;
- }
- else { /* format == GENERALIZED_TIME */
- year += btoi(date[i++]) * 1000;
- year += btoi(date[i++]) * 100;
- }
+ ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx);
+ if (ret < 0)
+ return ret;
- val = year;
- GetTime(&val, date, &i);
- year = (CPU_INT16U)val;
+ if (*len > 0) {
+ /* remove leading zero, unless there is only one 0x00 byte */
+ if ((input[*inOutIdx] == 0x00) && (*len > 1)) {
+ (*inOutIdx)++;
+ (*len)--;
- val = 0;
- GetTime(&val, date, &i);
- month = (CPU_INT08U)val;
+ if (*len > 0 && (input[*inOutIdx] & 0x80) == 0)
+ return ASN_PARSE_E;
+ }
+ }
- val = 0;
- GetTime(&val, date, &i);
- day = (CPU_INT16U)val;
+ return 0;
+}
- val = 0;
- GetTime(&val, date, &i);
- hour = (CPU_INT08U)val;
+/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than
+ * 7 bits.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_PARSE_E when the INTEGER tag is not found or length is invalid.
+ * Otherwise, the 7-bit value.
+ */
+static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ byte b;
- val = 0;
- GetTime(&val, date, &i);
- min = (CPU_INT08U)val;
+ if ((idx + 3) > maxIdx)
+ return BUFFER_E;
- val = 0;
- GetTime(&val, date, &i);
- sec = (CPU_INT08U)val;
+ if (GetASNTag(input, &idx, &b, maxIdx) != 0)
+ return ASN_PARSE_E;
+ if (b != ASN_INTEGER)
+ return ASN_PARSE_E;
+ if (input[idx++] != 1)
+ return ASN_PARSE_E;
+ b = input[idx++];
- return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType);
+ *inOutIdx = idx;
+ return b;
}
-#endif /* MICRIUM */
+#if !defined(NO_DSA) && !defined(NO_SHA)
+static const char sigSha1wDsaName[] = "SHAwDSA";
+#endif /* NO_DSA */
+#ifndef NO_RSA
+#ifdef WOLFSSL_MD2
+ static const char sigMd2wRsaName[] = "md2WithRSAEncryption";
+#endif
+#ifndef NO_MD5
+ static const char sigMd5wRsaName[] = "md5WithRSAEncryption";
+#endif
+#ifndef NO_SHA
+ static const char sigSha1wRsaName[] = "sha1WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA224
+ static const char sigSha224wRsaName[] = "sha224WithRSAEncryption";
+#endif
+#ifndef NO_SHA256
+ static const char sigSha256wRsaName[] = "sha256WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA384
+ static const char sigSha384wRsaName[] = "sha384WithRSAEncryption";
+#endif
+#ifdef WOLFSSL_SHA512
+ static const char sigSha512wRsaName[] = "sha512WithRSAEncryption";
+#endif
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+#ifndef NO_SHA
+ static const char sigSha1wEcdsaName[] = "SHAwECDSA";
+#endif
+#ifdef WOLFSSL_SHA224
+ static const char sigSha224wEcdsaName[] = "SHA224wECDSA";
+#endif
+#ifndef NO_SHA256
+ static const char sigSha256wEcdsaName[] = "SHA256wECDSA";
+#endif
+#ifdef WOLFSSL_SHA384
+ static const char sigSha384wEcdsaName[] = "SHA384wECDSA";
+#endif
+#ifdef WOLFSSL_SHA512
+ static const char sigSha512wEcdsaName[] = "SHA512wECDSA";
+#endif
+#endif /* HAVE_ECC */
+static const char sigUnknownName[] = "Unknown";
-WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
- word32 maxIdx)
-{
- int length = 0;
- word32 i = *inOutIdx;
- byte b;
-
- *len = 0; /* default length */
- if ( (i+1) > maxIdx) { /* for first read */
- WOLFSSL_MSG("GetLength bad index on input");
- return BUFFER_E;
+/* Get the human readable string for a signature type
+ *
+ * oid Oid value for signature
+ */
+const char* GetSigName(int oid) {
+ switch (oid) {
+ #if !defined(NO_DSA) && !defined(NO_SHA)
+ case CTC_SHAwDSA:
+ return sigSha1wDsaName;
+ #endif /* NO_DSA && NO_SHA */
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ case CTC_MD2wRSA:
+ return sigMd2wRsaName;
+ #endif
+ #ifndef NO_MD5
+ case CTC_MD5wRSA:
+ return sigMd5wRsaName;
+ #endif
+ #ifndef NO_SHA
+ case CTC_SHAwRSA:
+ return sigSha1wRsaName;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wRSA:
+ return sigSha224wRsaName;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wRSA:
+ return sigSha256wRsaName;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wRSA:
+ return sigSha384wRsaName;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wRSA:
+ return sigSha512wRsaName;
+ #endif
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ #ifndef NO_SHA
+ case CTC_SHAwECDSA:
+ return sigSha1wEcdsaName;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wECDSA:
+ return sigSha224wEcdsaName;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wECDSA:
+ return sigSha256wEcdsaName;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wECDSA:
+ return sigSha384wEcdsaName;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wECDSA:
+ return sigSha512wEcdsaName;
+ #endif
+ #endif /* HAVE_ECC */
+ default:
+ return sigUnknownName;
}
+}
- b = input[i++];
- if (b >= ASN_LONG_LENGTH) {
- word32 bytes = b & 0x7F;
- if ( (i+bytes) > maxIdx) { /* for reading bytes */
- WOLFSSL_MSG("GetLength bad long length");
- return BUFFER_E;
- }
+#if !defined(NO_DSA) || defined(HAVE_ECC) || !defined(NO_CERTS) || \
+ (!defined(NO_RSA) && \
+ (defined(WOLFSSL_CERT_GEN) || \
+ ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA))))
+/* Set the DER/BER encoding of the ASN.1 INTEGER header.
+ *
+ * len Length of data to encode.
+ * firstByte First byte of data, most significant byte of integer, to encode.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static int SetASNInt(int len, byte firstByte, byte* output)
+{
+ word32 idx = 0;
- while (bytes--) {
- b = input[i++];
- length = (length << 8) | b;
- }
- }
- else
- length = b;
-
- if ( (i+length) > maxIdx) { /* for user of length */
- WOLFSSL_MSG("GetLength value exceeds buffer length");
- return BUFFER_E;
+ if (output)
+ output[idx] = ASN_INTEGER;
+ idx++;
+ if (firstByte & 0x80)
+ len++;
+ idx += SetLength(len, output ? output + idx : NULL);
+ if (firstByte & 0x80) {
+ if (output)
+ output[idx] = 0x00;
+ idx++;
}
- *inOutIdx = i;
- if (length > 0)
- *len = length;
-
- return length;
+ return idx;
}
+#endif
-
-WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
- word32 maxIdx)
+#if !defined(NO_DSA) || defined(HAVE_ECC) || (defined(WOLFSSL_CERT_GEN) && \
+ !defined(NO_RSA)) || ((defined(WOLFSSL_KEY_GEN) || \
+ defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA))
+/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int.
+ * The number is assumed to be positive.
+ *
+ * n Multi-precision integer to encode.
+ * maxSz Maximum size of the encoded integer.
+ * A negative value indicates no check of length requested.
+ * output Buffer to write into.
+ * returns BUFFER_E when the data is too long for the buffer.
+ * MP_TO_E when encoding the integer fails.
+ * Otherwise, the number of bytes added to the buffer.
+ */
+static int SetASNIntMP(mp_int* n, int maxSz, byte* output)
{
- int length = -1;
- word32 idx = *inOutIdx;
+ int idx = 0;
+ int leadingBit;
+ int length;
+ int err;
- if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) ||
- GetLength(input, &idx, &length, maxIdx) < 0)
- return ASN_PARSE_E;
+ leadingBit = mp_leading_bit(n);
+ length = mp_unsigned_bin_size(n);
+ idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
+ if (maxSz >= 0 && (idx + length) > maxSz)
+ return BUFFER_E;
- *len = length;
- *inOutIdx = idx;
+ if (output) {
+ err = mp_to_unsigned_bin(n, output + idx);
+ if (err != MP_OKAY)
+ return MP_TO_E;
+ }
+ idx += length;
- return length;
+ return idx;
}
+#endif
-
-WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
- word32 maxIdx)
+#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && \
+ (defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA))
+/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from
+ * an RSA key.
+ * The number is assumed to be positive.
+ *
+ * n Multi-precision integer to encode.
+ * output Buffer to write into.
+ * returns BUFFER_E when the data is too long for the buffer.
+ * MP_TO_E when encoding the integer fails.
+ * Otherwise, the number of bytes added to the buffer.
+ */
+static int SetASNIntRSA(void* n, byte* output)
{
- int length = -1;
- word32 idx = *inOutIdx;
+ int idx = 0;
+ int leadingBit;
+ int length;
+ int err;
- if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) ||
- GetLength(input, &idx, &length, maxIdx) < 0)
- return ASN_PARSE_E;
+ leadingBit = wc_Rsa_leading_bit(n);
+ length = wc_Rsa_unsigned_bin_size(n);
+ idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
+ if ((idx + length) > MAX_RSA_INT_SZ)
+ return BUFFER_E;
- *len = length;
- *inOutIdx = idx;
+ if (output) {
+ err = wc_Rsa_to_unsigned_bin(n, output + idx, length);
+ if (err != MP_OKAY)
+ return MP_TO_E;
+ }
+ idx += length;
- return length;
+ return idx;
}
+#endif /* !NO_RSA && HAVE_USER_RSA && WOLFSSL_CERT_GEN */
-
-/* winodws header clash for WinCE using GetVersion */
-WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version)
+/* Windows header clash for WinCE using GetVersion */
+int GetMyVersion(const byte* input, word32* inOutIdx,
+ int* version, word32 maxIdx)
{
word32 idx = *inOutIdx;
+ byte tag;
- WOLFSSL_ENTER("GetMyVersion");
+ if ((idx + MIN_VERSION_SZ) > maxIdx)
+ return ASN_PARSE_E;
- if (input[idx++] != ASN_INTEGER)
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+ return ASN_PARSE_E;
+
+ if (tag != ASN_INTEGER)
return ASN_PARSE_E;
if (input[idx++] != 0x01)
@@ -550,20 +746,31 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version
#ifndef NO_PWDBASED
/* Get small count integer, 32 bits or less */
-static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
+int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx)
{
word32 idx = *inOutIdx;
word32 len;
+ byte tag;
*number = 0;
- if (input[idx++] != ASN_INTEGER)
+ /* check for type and length bytes */
+ if ((idx + 2) > maxIdx)
+ return BUFFER_E;
+
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+ return ASN_PARSE_E;
+
+ if (tag != ASN_INTEGER)
return ASN_PARSE_E;
len = input[idx++];
if (len > 4)
return ASN_PARSE_E;
+ if (len + idx > maxIdx)
+ return ASN_PARSE_E;
+
while (len--) {
*number = *number << 8 | input[idx++];
}
@@ -572,18 +779,68 @@ static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
return *number;
}
-#endif /* !NO_PWDBASED */
+/* Set small integer, 32 bits or less. DER encoding with no leading 0s
+ * returns total amount written including ASN tag and length byte on success */
+int SetShortInt(byte* input, word32* inOutIdx, word32 number, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ word32 len = 0;
+ int i;
+ byte ar[MAX_LENGTH_SZ];
+
+ /* check for room for type and length bytes */
+ if ((idx + 2) > maxIdx)
+ return BUFFER_E;
+
+ input[idx++] = ASN_INTEGER;
+ idx++; /* place holder for length byte */
+ if (MAX_LENGTH_SZ + idx > maxIdx)
+ return ASN_PARSE_E;
+
+ /* find first non zero byte */
+ XMEMSET(ar, 0, MAX_LENGTH_SZ);
+ c32toa(number, ar);
+ for (i = 0; i < MAX_LENGTH_SZ; i++) {
+ if (ar[i] != 0) {
+ break;
+ }
+ }
+
+ /* handle case of 0 */
+ if (i == MAX_LENGTH_SZ) {
+ input[idx++] = 0; len++;
+ }
+
+ for (; i < MAX_LENGTH_SZ && idx < maxIdx; i++) {
+ input[idx++] = ar[i]; len++;
+ }
+
+ /* jump back to beginning of input buffer using unaltered inOutIdx value
+ * and set number of bytes for integer, then update the index value */
+ input[*inOutIdx + 1] = (byte)len;
+ *inOutIdx = idx;
+
+ return len + 2; /* size of integer bytes plus ASN TAG and length byte */
+}
+#endif /* !NO_PWDBASED */
+
/* May not have one, not an error */
-static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
+static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version,
+ word32 maxIdx)
{
word32 idx = *inOutIdx;
+ byte tag;
WOLFSSL_ENTER("GetExplicitVersion");
- if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
- *inOutIdx = ++idx; /* eat header */
- return GetMyVersion(input, inOutIdx, version);
+
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
+ return ASN_PARSE_E;
+
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+ *inOutIdx = ++idx; /* skip header */
+ return GetMyVersion(input, inOutIdx, version, maxIdx);
}
/* go back as is */
@@ -592,257 +849,2267 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
return 0;
}
-
-WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
- word32 maxIdx)
+int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx)
{
- word32 i = *inOutIdx;
- byte b = input[i++];
+ word32 idx = *inOutIdx;
+ int ret;
int length;
- if (b != ASN_INTEGER)
- return ASN_PARSE_E;
-
- if (GetLength(input, &i, &length, maxIdx) < 0)
- return ASN_PARSE_E;
-
- if ( (b = input[i++]) == 0x00)
- length--;
- else
- i--;
+ ret = GetASNInt(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
if (mp_init(mpi) != MP_OKAY)
return MP_INIT_E;
- if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) {
+ if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) {
+ mp_clear(mpi);
+ return ASN_GETINT_E;
+ }
+
+#ifdef HAVE_WOLF_BIGINT
+ if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) {
mp_clear(mpi);
return ASN_GETINT_E;
}
+#endif /* HAVE_WOLF_BIGINT */
+
+ *inOutIdx = idx + length;
- *inOutIdx = i + length;
return 0;
}
+#if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \
+ || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA) && defined(WOLFSSL_QT))
+#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ int ret;
+ int length;
-static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
- word32 maxIdx)
+ ret = GetASNInt(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
+
+ *inOutIdx = idx + length;
+
+ return 0;
+}
+#endif
+#endif
+
+static int CheckBitString(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx, int zeroBits, byte* unusedBits)
{
+ word32 idx = *inOutIdx;
int length;
- word32 i = *inOutIdx;
byte b;
- *oid = 0;
-
- b = input[i++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(input, &i, &length, maxIdx) < 0)
+
+ if (GetASNTag(input, &idx, &b, maxIdx) != 0) {
+ return ASN_BITSTR_E;
+ }
+
+ if (b != ASN_BIT_STRING) {
+ return ASN_BITSTR_E;
+ }
+
+ if (GetLength(input, &idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
-
- while(length--)
- *oid += input[i++];
- /* just sum it up for now */
-
- *inOutIdx = i;
-
+
+ /* extra sanity check that length is greater than 0 */
+ if (length <= 0) {
+ WOLFSSL_MSG("Error length was 0 in CheckBitString");
+ return BUFFER_E;
+ }
+
+ if (idx + 1 > maxIdx) {
+ WOLFSSL_MSG("Attempted buffer read larger than input buffer");
+ return BUFFER_E;
+ }
+
+ b = input[idx];
+ if (zeroBits && b != 0x00)
+ return ASN_EXPECT_0_E;
+ if (b >= 0x08)
+ return ASN_PARSE_E;
+ if (b != 0) {
+ if ((byte)(input[idx + length - 1] << (8 - b)) != 0)
+ return ASN_PARSE_E;
+ }
+ idx++;
+ length--; /* length has been checked for greater than 0 */
+
+ *inOutIdx = idx;
+ if (len != NULL)
+ *len = length;
+ if (unusedBits != NULL)
+ *unusedBits = b;
+
return 0;
}
+/* RSA (with CertGen or KeyGen) OR ECC OR ED25519 OR ED448 (with CertGen or
+ * KeyGen) */
+#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \
+ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \
+ (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) || \
+ ((defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
+ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)))
-WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
- word32 maxIdx)
+/* Set the DER/BER encoding of the ASN.1 BIT_STRING header.
+ *
+ * len Length of data to encode.
+ * unusedBits The number of unused bits in the last byte of data.
+ * That is, the number of least significant zero bits before a one.
+ * The last byte is the most-significant non-zero byte of a number.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+word32 SetBitString(word32 len, byte unusedBits, byte* output)
{
- int length;
- word32 i = *inOutIdx;
- byte b;
- *oid = 0;
-
- WOLFSSL_ENTER("GetAlgoId");
+ word32 idx = 0;
- if (GetSequence(input, &i, &length, maxIdx) < 0)
- return ASN_PARSE_E;
-
- b = input[i++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(input, &i, &length, maxIdx) < 0)
+ if (output)
+ output[idx] = ASN_BIT_STRING;
+ idx++;
+
+ idx += SetLength(len + 1, output ? output + idx : NULL);
+ if (output)
+ output[idx] = unusedBits;
+ idx++;
+
+ return idx;
+}
+#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
+
+#ifdef ASN_BER_TO_DER
+/* Pull informtation from the ASN.1 BER encoded item header */
+static int GetBerHeader(const byte* data, word32* idx, word32 maxIdx,
+ byte* pTag, word32* pLen, int* indef)
+{
+ int len = 0;
+ byte tag;
+ word32 i = *idx;
+
+ *indef = 0;
+
+ /* Check there is enough data for a minimal header */
+ if (i + 2 > maxIdx) {
return ASN_PARSE_E;
-
- while(length--) {
- /* odd HC08 compiler behavior here when input[i++] */
- *oid += input[i];
+ }
+
+ /* Retrieve tag */
+ tag = data[i++];
+
+ /* Indefinite length handled specially */
+ if (data[i] == 0x80) {
+ /* Check valid tag for indefinite */
+ if (((tag & 0xc0) == 0) && ((tag & ASN_CONSTRUCTED) == 0x00)) {
+ return ASN_PARSE_E;
+ }
i++;
+ *indef = 1;
}
- /* just sum it up for now */
-
- /* could have NULL tag and 0 terminator, but may not */
- b = input[i++];
-
- if (b == ASN_TAG_NULL) {
- b = input[i++];
- if (b != 0)
- return ASN_EXPECT_0_E;
+ else if (GetLength(data, &i, &len, maxIdx) < 0) {
+ return ASN_PARSE_E;
}
- else
- /* go back, didn't have it */
- i--;
-
- *inOutIdx = i;
-
+
+ /* Return tag, length and index after BER item header */
+ *pTag = tag;
+ *pLen = len;
+ *idx = i;
return 0;
}
+#ifndef INDEF_ITEMS_MAX
+#define INDEF_ITEMS_MAX 20
+#endif
+
+/* Indef length item data */
+typedef struct Indef {
+ word32 start;
+ int depth;
+ int headerLen;
+ word32 len;
+} Indef;
+
+/* Indef length items */
+typedef struct IndefItems
+{
+ Indef len[INDEF_ITEMS_MAX];
+ int cnt;
+ int idx;
+ int depth;
+} IndefItems;
+
+
+/* Get header length of current item */
+static int IndefItems_HeaderLen(IndefItems* items)
+{
+ return items->len[items->idx].headerLen;
+}
+
+/* Get data length of current item */
+static word32 IndefItems_Len(IndefItems* items)
+{
+ return items->len[items->idx].len;
+}
+
+/* Add a indefinite length item */
+static int IndefItems_AddItem(IndefItems* items, word32 start)
+{
+ int ret = 0;
+ int i;
+
+ if (items->cnt == INDEF_ITEMS_MAX) {
+ ret = MEMORY_E;
+ }
+ else {
+ i = items->cnt++;
+ items->len[i].start = start;
+ items->len[i].depth = items->depth++;
+ items->len[i].headerLen = 1;
+ items->len[i].len = 0;
+ items->idx = i;
+ }
+
+ return ret;
+}
+
+/* Increase data length of current item */
+static void IndefItems_AddData(IndefItems* items, word32 length)
+{
+ items->len[items->idx].len += length;
+}
+
+/* Update header length of current item to reflect data length */
+static void IndefItems_UpdateHeaderLen(IndefItems* items)
+{
+ items->len[items->idx].headerLen +=
+ SetLength(items->len[items->idx].len, NULL);
+}
+
+/* Go to indefinite parent of current item */
+static void IndefItems_Up(IndefItems* items)
+{
+ int i;
+ int depth = items->len[items->idx].depth - 1;
+
+ for (i = items->cnt - 1; i >= 0; i--) {
+ if (items->len[i].depth == depth) {
+ break;
+ }
+ }
+ items->idx = i;
+ items->depth = depth + 1;
+}
+
+/* Calculate final length by adding length of indefinite child items */
+static void IndefItems_CalcLength(IndefItems* items)
+{
+ int i;
+ int idx = items->idx;
+
+ for (i = idx + 1; i < items->cnt; i++) {
+ if (items->len[i].depth == items->depth) {
+ items->len[idx].len += items->len[i].headerLen;
+ items->len[idx].len += items->len[i].len;
+ }
+ }
+ items->len[idx].headerLen += SetLength(items->len[idx].len, NULL);
+}
+
+/* Add more data to indefinite length item */
+static void IndefItems_MoreData(IndefItems* items, word32 length)
+{
+ if (items->cnt > 0 && items->idx >= 0) {
+ items->len[items->idx].len += length;
+ }
+}
+
+/* Convert a BER encoding with indefinite length items to DER.
+ *
+ * ber BER encoded data.
+ * berSz Length of BER encoded data.
+ * der Buffer to hold DER encoded version of data.
+ * NULL indicates only the length is required.
+ * derSz The size of the buffer to hold the DER encoded data.
+ * Will be set if der is NULL, otherwise the value is checked as der is
+ * filled.
+ * returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or
+ * derSz are NULL.
+ */
+int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz)
+{
+ int ret = 0;
+ word32 i, j;
+#ifdef WOLFSSL_SMALL_STACK
+ IndefItems* indefItems = NULL;
+#else
+ IndefItems indefItems[1];
+#endif
+ byte tag, basic;
+ word32 length;
+ int indef;
+
+ if (ber == NULL || derSz == NULL)
+ return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+ indefItems = XMALLOC(sizeof(IndefItems), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (indefItems == NULL) {
+ ret = MEMORY_E;
+ goto end;
+ }
+#endif
+
+ XMEMSET(indefItems, 0, sizeof(*indefItems));
+
+ /* Calculate indefinite item lengths */
+ for (i = 0; i < berSz; ) {
+ word32 start = i;
+
+ /* Get next BER item */
+ ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (ret != 0) {
+ goto end;
+ }
+
+ if (indef) {
+ /* Indefinite item - add to list */
+ ret = IndefItems_AddItem(indefItems, i);
+ if (ret != 0) {
+ goto end;
+ }
+
+ if ((tag & 0xC0) == 0 &&
+ tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+ tag != (ASN_SET | ASN_CONSTRUCTED)) {
+ /* Constructed basic type - get repeating tag */
+ basic = tag & (~ASN_CONSTRUCTED);
+
+ /* Add up lengths of each item below */
+ for (; i < berSz; ) {
+ /* Get next BER_item */
+ ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (ret != 0) {
+ goto end;
+ }
+
+ /* End of content closes item */
+ if (tag == ASN_EOC) {
+ /* Must be zero length */
+ if (length != 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+ break;
+ }
+
+ /* Must not be indefinite and tag must match parent */
+ if (indef || tag != basic) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Add to length */
+ IndefItems_AddData(indefItems, length);
+ /* Skip data */
+ i += length;
+ }
+
+ /* Ensure we got an EOC and not end of data */
+ if (tag != ASN_EOC) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Set the header length to include the length field */
+ IndefItems_UpdateHeaderLen(indefItems);
+ /* Go to indefinte parent item */
+ IndefItems_Up(indefItems);
+ }
+ }
+ else if (tag == ASN_EOC) {
+ /* End-of-content must be 0 length */
+ if (length != 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+ /* Check there is an item to close - missing EOC */
+ if (indefItems->depth == 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Finish calculation of data length for indefinite item */
+ IndefItems_CalcLength(indefItems);
+ /* Go to indefinte parent item */
+ IndefItems_Up(indefItems);
+ }
+ else {
+ /* Known length item to add in - make sure enough data for it */
+ if (i + length > berSz) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Include all data - can't have indefinite inside definite */
+ i += length;
+ /* Add entire item to current indefinite item */
+ IndefItems_MoreData(indefItems, i - start);
+ }
+ }
+ /* Check we had a EOC for each indefinite item */
+ if (indefItems->depth != 0) {
+ ret = ASN_PARSE_E;
+ goto end;
+ }
+
+ /* Write out DER */
+
+ j = 0;
+ /* Reset index */
+ indefItems->idx = 0;
+ for (i = 0; i < berSz; ) {
+ word32 start = i;
+
+ /* Get item - checked above */
+ (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (indef) {
+ if (der != NULL) {
+ /* Check enough space for header */
+ if (j + IndefItems_HeaderLen(indefItems) > *derSz) {
+ ret = BUFFER_E;
+ goto end;
+ }
+
+ if ((tag & 0xC0) == 0 &&
+ tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+ tag != (ASN_SET | ASN_CONSTRUCTED)) {
+ /* Remove constructed tag for basic types */
+ tag &= ~ASN_CONSTRUCTED;
+ }
+ /* Add tag and length */
+ der[j] = tag;
+ (void)SetLength(IndefItems_Len(indefItems), der + j + 1);
+ }
+ /* Add header length of indefinite item */
+ j += IndefItems_HeaderLen(indefItems);
+
+ if ((tag & 0xC0) == 0 &&
+ tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
+ tag != (ASN_SET | ASN_CONSTRUCTED)) {
+ /* For basic type - get each child item and add data */
+ for (; i < berSz; ) {
+ (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
+ if (tag == ASN_EOC) {
+ break;
+ }
+ if (der != NULL) {
+ if (j + length > *derSz) {
+ ret = BUFFER_E;
+ goto end;
+ }
+ XMEMCPY(der + j, ber + i, length);
+ }
+ j += length;
+ i += length;
+ }
+ }
+
+ /* Move to next indef item in list */
+ indefItems->idx++;
+ }
+ else if (tag == ASN_EOC) {
+ /* End-Of-Content is not written out in DER */
+ }
+ else {
+ /* Write out definite length item as is. */
+ i += length;
+ if (der != NULL) {
+ /* Ensure space for item */
+ if (j + i - start > *derSz) {
+ ret = BUFFER_E;
+ goto end;
+ }
+ /* Copy item as is */
+ XMEMCPY(der + j, ber + start, i - start);
+ }
+ j += i - start;
+ }
+ }
+
+ /* Return the length of the DER encoded ASN.1 */
+ *derSz = j;
+ if (der == NULL) {
+ ret = LENGTH_ONLY_E;
+ }
+end:
+#ifdef WOLFSSL_SMALL_STACK
+ if (indefItems != NULL) {
+ XFREE(indefItems, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+#endif
+ return ret;
+}
+#endif
+
+#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
+
+#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
+ defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
+
+#ifdef WOLFSSL_CERT_EXT
+/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value.
+ *
+ * val 16-bit value to encode.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+static word32 SetBitString16Bit(word16 val, byte* output)
+{
+ word32 idx;
+ int len;
+ byte lastByte;
+ byte unusedBits = 0;
+
+ if ((val >> 8) != 0) {
+ len = 2;
+ lastByte = (byte)(val >> 8);
+ }
+ else {
+ len = 1;
+ lastByte = (byte)val;
+ }
+
+ while (((lastByte >> unusedBits) & 0x01) == 0x00)
+ unusedBits++;
+
+ idx = SetBitString(len, unusedBits, output);
+ output[idx++] = (byte)val;
+ if (len > 1)
+ output[idx++] = (byte)(val >> 8);
+
+ return idx;
+}
+#endif /* WOLFSSL_CERT_EXT */
+#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448) */
+#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */
+
+
+
+/* hashType */
+#ifdef WOLFSSL_MD2
+ static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2};
+#endif
+#ifndef NO_MD5
+ static const byte hashMd5hOid[] = {42, 134, 72, 134, 247, 13, 2, 5};
+#endif
+#ifndef NO_SHA
+ static const byte hashSha1hOid[] = {43, 14, 3, 2, 26};
+#endif
+#ifdef WOLFSSL_SHA224
+ static const byte hashSha224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 4};
+#endif
+#ifndef NO_SHA256
+ static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1};
+#endif
+#ifdef WOLFSSL_SHA384
+ static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2};
+#endif
+#ifdef WOLFSSL_SHA512
+ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3};
+#endif
+
+/* hmacType */
+#ifndef NO_HMAC
+ #ifdef WOLFSSL_SHA224
+ static const byte hmacSha224Oid[] = {42, 134, 72, 134, 247, 13, 2, 8};
+ #endif
+ #ifndef NO_SHA256
+ static const byte hmacSha256Oid[] = {42, 134, 72, 134, 247, 13, 2, 9};
+ #endif
+ #ifdef WOLFSSL_SHA384
+ static const byte hmacSha384Oid[] = {42, 134, 72, 134, 247, 13, 2, 10};
+ #endif
+ #ifdef WOLFSSL_SHA512
+ static const byte hmacSha512Oid[] = {42, 134, 72, 134, 247, 13, 2, 11};
+ #endif
+#endif
+
+/* sigType */
+#if !defined(NO_DSA) && !defined(NO_SHA)
+ static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3};
+#endif /* NO_DSA */
#ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ static const byte sigMd2wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 2};
+ #endif
+ #ifndef NO_MD5
+ static const byte sigMd5wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 4};
+ #endif
+ #ifndef NO_SHA
+ static const byte sigSha1wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 5};
+ #endif
+ #ifdef WOLFSSL_SHA224
+ static const byte sigSha224wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,14};
+ #endif
+ #ifndef NO_SHA256
+ static const byte sigSha256wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,11};
+ #endif
+ #ifdef WOLFSSL_SHA384
+ static const byte sigSha384wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,12};
+ #endif
+ #ifdef WOLFSSL_SHA512
+ static const byte sigSha512wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,13};
+ #endif
+#endif /* NO_RSA */
+#ifdef HAVE_ECC
+ #ifndef NO_SHA
+ static const byte sigSha1wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 1};
+ #endif
+ #ifdef WOLFSSL_SHA224
+ static const byte sigSha224wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 1};
+ #endif
+ #ifndef NO_SHA256
+ static const byte sigSha256wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 2};
+ #endif
+ #ifdef WOLFSSL_SHA384
+ static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3};
+ #endif
+ #ifdef WOLFSSL_SHA512
+ static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4};
+ #endif
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+ static const byte sigEd25519Oid[] = {43, 101, 112};
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+ static const byte sigEd448Oid[] = {43, 101, 113};
+#endif /* HAVE_ED448 */
+
+/* keyType */
+#ifndef NO_DSA
+ static const byte keyDsaOid[] = {42, 134, 72, 206, 56, 4, 1};
+#endif /* NO_DSA */
+#ifndef NO_RSA
+ static const byte keyRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 1};
+#endif /* NO_RSA */
+#ifdef HAVE_NTRU
+ static const byte keyNtruOid[] = {43, 6, 1, 4, 1, 193, 22, 1, 1, 1, 1};
+#endif /* HAVE_NTRU */
+#ifdef HAVE_ECC
+ static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1};
+#endif /* HAVE_ECC */
+#ifdef HAVE_ED25519
+ static const byte keyEd25519Oid[] = {43, 101, 112};
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+ static const byte keyEd448Oid[] = {43, 101, 113};
+#endif /* HAVE_ED448 */
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1};
+#endif /* ! NO_DH ... */
+
+/* curveType */
+#ifdef HAVE_ECC
+ /* See "ecc_sets" table in ecc.c */
+#endif /* HAVE_ECC */
+#ifdef HAVE_AES_CBC
+/* blkType */
+ #ifdef WOLFSSL_AES_128
+ static const byte blkAes128CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 2};
+ #endif
+ #ifdef WOLFSSL_AES_192
+ static const byte blkAes192CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 22};
+ #endif
+ #ifdef WOLFSSL_AES_256
+ static const byte blkAes256CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 42};
+ #endif
+#endif /* HAVE_AES_CBC */
+#ifdef HAVE_AESGCM
+ #ifdef WOLFSSL_AES_128
+ static const byte blkAes128GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 6};
+ #endif
+ #ifdef WOLFSSL_AES_192
+ static const byte blkAes192GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 26};
+ #endif
+ #ifdef WOLFSSL_AES_256
+ static const byte blkAes256GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 46};
+ #endif
+#endif /* HAVE_AESGCM */
+#ifdef HAVE_AESCCM
+ #ifdef WOLFSSL_AES_128
+ static const byte blkAes128CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 7};
+ #endif
+ #ifdef WOLFSSL_AES_192
+ static const byte blkAes192CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 27};
+ #endif
+ #ifdef WOLFSSL_AES_256
+ static const byte blkAes256CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 47};
+ #endif
+#endif /* HAVE_AESCCM */
-#ifdef HAVE_CAVIUM
+#ifndef NO_DES3
+ static const byte blkDesCbcOid[] = {43, 14, 3, 2, 7};
+ static const byte blkDes3CbcOid[] = {42, 134, 72, 134, 247, 13, 3, 7};
+#endif
-static int GetCaviumInt(byte** buff, word16* buffSz, const byte* input,
- word32* inOutIdx, word32 maxIdx, void* heap)
+/* keyWrapType */
+#ifdef WOLFSSL_AES_128
+ static const byte wrapAes128Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 5};
+#endif
+#ifdef WOLFSSL_AES_192
+ static const byte wrapAes192Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 25};
+#endif
+#ifdef WOLFSSL_AES_256
+ static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45};
+#endif
+#ifdef HAVE_PKCS7
+/* From RFC 3211 */
+static const byte wrapPwriKekOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3,9};
+#endif
+
+/* cmsKeyAgreeType */
+#ifndef NO_SHA
+ static const byte dhSinglePass_stdDH_sha1kdf_Oid[] =
+ {43, 129, 5, 16, 134, 72, 63, 0, 2};
+#endif
+#ifdef WOLFSSL_SHA224
+ static const byte dhSinglePass_stdDH_sha224kdf_Oid[] = {43, 129, 4, 1, 11, 0};
+#endif
+#ifndef NO_SHA256
+ static const byte dhSinglePass_stdDH_sha256kdf_Oid[] = {43, 129, 4, 1, 11, 1};
+#endif
+#ifdef WOLFSSL_SHA384
+ static const byte dhSinglePass_stdDH_sha384kdf_Oid[] = {43, 129, 4, 1, 11, 2};
+#endif
+#ifdef WOLFSSL_SHA512
+ static const byte dhSinglePass_stdDH_sha512kdf_Oid[] = {43, 129, 4, 1, 11, 3};
+#endif
+
+/* ocspType */
+#ifdef HAVE_OCSP
+ static const byte ocspBasicOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 1};
+ static const byte ocspNonceOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 2};
+#endif /* HAVE_OCSP */
+
+/* certExtType */
+static const byte extBasicCaOid[] = {85, 29, 19};
+static const byte extAltNamesOid[] = {85, 29, 17};
+static const byte extCrlDistOid[] = {85, 29, 31};
+static const byte extAuthInfoOid[] = {43, 6, 1, 5, 5, 7, 1, 1};
+static const byte extAuthKeyOid[] = {85, 29, 35};
+static const byte extSubjKeyOid[] = {85, 29, 14};
+static const byte extCertPolicyOid[] = {85, 29, 32};
+static const byte extKeyUsageOid[] = {85, 29, 15};
+static const byte extInhibitAnyOid[] = {85, 29, 54};
+static const byte extExtKeyUsageOid[] = {85, 29, 37};
+#ifndef IGNORE_NAME_CONSTRAINTS
+ static const byte extNameConsOid[] = {85, 29, 30};
+#endif
+
+/* certAuthInfoType */
+#ifdef HAVE_OCSP
+ static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1};
+#endif
+static const byte extAuthInfoCaIssuerOid[] = {43, 6, 1, 5, 5, 7, 48, 2};
+
+/* certPolicyType */
+static const byte extCertPolicyAnyOid[] = {85, 29, 32, 0};
+
+/* certKeyUseType */
+static const byte extAltNamesHwNameOid[] = {43, 6, 1, 5, 5, 7, 8, 4};
+
+/* certKeyUseType */
+static const byte extExtKeyUsageAnyOid[] = {85, 29, 37, 0};
+static const byte extExtKeyUsageServerAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 1};
+static const byte extExtKeyUsageClientAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 2};
+static const byte extExtKeyUsageCodeSigningOid[] = {43, 6, 1, 5, 5, 7, 3, 3};
+static const byte extExtKeyUsageEmailProtectOid[] = {43, 6, 1, 5, 5, 7, 3, 4};
+static const byte extExtKeyUsageTimestampOid[] = {43, 6, 1, 5, 5, 7, 3, 8};
+static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9};
+
+/* kdfType */
+static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12};
+
+/* PKCS5 */
+#if !defined(NO_DES3) && !defined(NO_SHA)
+static const byte pbeSha1Des[] = {42, 134, 72, 134, 247, 13, 1, 5, 10};
+#endif
+static const byte pbes2[] = {42, 134, 72, 134, 247, 13, 1, 5, 13};
+
+/* PKCS12 */
+#if !defined(NO_RC4) && !defined(NO_SHA)
+static const byte pbeSha1RC4128[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 1};
+#endif
+#if !defined(NO_DES3) && !defined(NO_SHA)
+static const byte pbeSha1Des3[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 3};
+#endif
+
+#ifdef HAVE_LIBZ
+/* zlib compression */
+static const byte zlibCompress[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3, 8};
+#endif
+#ifdef WOLFSSL_APACHE_HTTPD
+/* tlsExtType */
+static const byte tlsFeatureOid[] = {43, 6, 1, 5, 5, 7, 1, 24};
+/* certNameType */
+static const byte dnsSRVOid[] = {43, 6, 1, 5, 5, 7, 8, 7};
+#endif
+
+
+/* returns a pointer to the OID string on success and NULL on fail */
+const byte* OidFromId(word32 id, word32 type, word32* oidSz)
{
- word32 i = *inOutIdx;
- byte b = input[i++];
+ const byte* oid = NULL;
+
+ *oidSz = 0;
+
+ switch (type) {
+
+ case oidHashType:
+ switch (id) {
+ #ifdef WOLFSSL_MD2
+ case MD2h:
+ oid = hashMd2hOid;
+ *oidSz = sizeof(hashMd2hOid);
+ break;
+ #endif
+ #ifndef NO_MD5
+ case MD5h:
+ oid = hashMd5hOid;
+ *oidSz = sizeof(hashMd5hOid);
+ break;
+ #endif
+ #ifndef NO_SHA
+ case SHAh:
+ oid = hashSha1hOid;
+ *oidSz = sizeof(hashSha1hOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case SHA224h:
+ oid = hashSha224hOid;
+ *oidSz = sizeof(hashSha224hOid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case SHA256h:
+ oid = hashSha256hOid;
+ *oidSz = sizeof(hashSha256hOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case SHA384h:
+ oid = hashSha384hOid;
+ *oidSz = sizeof(hashSha384hOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case SHA512h:
+ oid = hashSha512hOid;
+ *oidSz = sizeof(hashSha512hOid);
+ break;
+ #endif
+ }
+ break;
+
+ case oidSigType:
+ switch (id) {
+ #if !defined(NO_DSA) && !defined(NO_SHA)
+ case CTC_SHAwDSA:
+ oid = sigSha1wDsaOid;
+ *oidSz = sizeof(sigSha1wDsaOid);
+ break;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_MD2
+ case CTC_MD2wRSA:
+ oid = sigMd2wRsaOid;
+ *oidSz = sizeof(sigMd2wRsaOid);
+ break;
+ #endif
+ #ifndef NO_MD5
+ case CTC_MD5wRSA:
+ oid = sigMd5wRsaOid;
+ *oidSz = sizeof(sigMd5wRsaOid);
+ break;
+ #endif
+ #ifndef NO_SHA
+ case CTC_SHAwRSA:
+ oid = sigSha1wRsaOid;
+ *oidSz = sizeof(sigSha1wRsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wRSA:
+ oid = sigSha224wRsaOid;
+ *oidSz = sizeof(sigSha224wRsaOid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wRSA:
+ oid = sigSha256wRsaOid;
+ *oidSz = sizeof(sigSha256wRsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wRSA:
+ oid = sigSha384wRsaOid;
+ *oidSz = sizeof(sigSha384wRsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wRSA:
+ oid = sigSha512wRsaOid;
+ *oidSz = sizeof(sigSha512wRsaOid);
+ break;
+ #endif /* WOLFSSL_SHA512 */
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ #ifndef NO_SHA
+ case CTC_SHAwECDSA:
+ oid = sigSha1wEcdsaOid;
+ *oidSz = sizeof(sigSha1wEcdsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wECDSA:
+ oid = sigSha224wEcdsaOid;
+ *oidSz = sizeof(sigSha224wEcdsaOid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case CTC_SHA256wECDSA:
+ oid = sigSha256wEcdsaOid;
+ *oidSz = sizeof(sigSha256wEcdsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wECDSA:
+ oid = sigSha384wEcdsaOid;
+ *oidSz = sizeof(sigSha384wEcdsaOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case CTC_SHA512wECDSA:
+ oid = sigSha512wEcdsaOid;
+ *oidSz = sizeof(sigSha512wEcdsaOid);
+ break;
+ #endif
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case CTC_ED25519:
+ oid = sigEd25519Oid;
+ *oidSz = sizeof(sigEd25519Oid);
+ break;
+ #endif
+ #ifdef HAVE_ED448
+ case CTC_ED448:
+ oid = sigEd448Oid;
+ *oidSz = sizeof(sigEd448Oid);
+ break;
+ #endif
+ default:
+ break;
+ }
+ break;
+
+ case oidKeyType:
+ switch (id) {
+ #ifndef NO_DSA
+ case DSAk:
+ oid = keyDsaOid;
+ *oidSz = sizeof(keyDsaOid);
+ break;
+ #endif /* NO_DSA */
+ #ifndef NO_RSA
+ case RSAk:
+ oid = keyRsaOid;
+ *oidSz = sizeof(keyRsaOid);
+ break;
+ #endif /* NO_RSA */
+ #ifdef HAVE_NTRU
+ case NTRUk:
+ oid = keyNtruOid;
+ *oidSz = sizeof(keyNtruOid);
+ break;
+ #endif /* HAVE_NTRU */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ oid = keyEcdsaOid;
+ *oidSz = sizeof(keyEcdsaOid);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ oid = keyEd25519Oid;
+ *oidSz = sizeof(keyEd25519Oid);
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ oid = keyEd448Oid;
+ *oidSz = sizeof(keyEd448Oid);
+ break;
+ #endif /* HAVE_ED448 */
+ #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ case DHk:
+ oid = keyDhOid;
+ *oidSz = sizeof(keyDhOid);
+ break;
+ #endif /* ! NO_DH && (WOLFSSL_QT || OPENSSL_ALL */
+ default:
+ break;
+ }
+ break;
+
+ #ifdef HAVE_ECC
+ case oidCurveType:
+ if (wc_ecc_get_oid(id, &oid, oidSz) < 0) {
+ WOLFSSL_MSG("ECC OID not found");
+ }
+ break;
+ #endif /* HAVE_ECC */
+
+ case oidBlkType:
+ switch (id) {
+ #ifdef HAVE_AES_CBC
+ #ifdef WOLFSSL_AES_128
+ case AES128CBCb:
+ oid = blkAes128CbcOid;
+ *oidSz = sizeof(blkAes128CbcOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192CBCb:
+ oid = blkAes192CbcOid;
+ *oidSz = sizeof(blkAes192CbcOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256CBCb:
+ oid = blkAes256CbcOid;
+ *oidSz = sizeof(blkAes256CbcOid);
+ break;
+ #endif
+ #endif /* HAVE_AES_CBC */
+ #ifdef HAVE_AESGCM
+ #ifdef WOLFSSL_AES_128
+ case AES128GCMb:
+ oid = blkAes128GcmOid;
+ *oidSz = sizeof(blkAes128GcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192GCMb:
+ oid = blkAes192GcmOid;
+ *oidSz = sizeof(blkAes192GcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256GCMb:
+ oid = blkAes256GcmOid;
+ *oidSz = sizeof(blkAes256GcmOid);
+ break;
+ #endif
+ #endif /* HAVE_AESGCM */
+ #ifdef HAVE_AESCCM
+ #ifdef WOLFSSL_AES_128
+ case AES128CCMb:
+ oid = blkAes128CcmOid;
+ *oidSz = sizeof(blkAes128CcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192CCMb:
+ oid = blkAes192CcmOid;
+ *oidSz = sizeof(blkAes192CcmOid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256CCMb:
+ oid = blkAes256CcmOid;
+ *oidSz = sizeof(blkAes256CcmOid);
+ break;
+ #endif
+ #endif /* HAVE_AESCCM */
+ #ifndef NO_DES3
+ case DESb:
+ oid = blkDesCbcOid;
+ *oidSz = sizeof(blkDesCbcOid);
+ break;
+ case DES3b:
+ oid = blkDes3CbcOid;
+ *oidSz = sizeof(blkDes3CbcOid);
+ break;
+ #endif /* !NO_DES3 */
+ }
+ break;
+
+ #ifdef HAVE_OCSP
+ case oidOcspType:
+ switch (id) {
+ case OCSP_BASIC_OID:
+ oid = ocspBasicOid;
+ *oidSz = sizeof(ocspBasicOid);
+ break;
+ case OCSP_NONCE_OID:
+ oid = ocspNonceOid;
+ *oidSz = sizeof(ocspNonceOid);
+ break;
+ }
+ break;
+ #endif /* HAVE_OCSP */
+
+ case oidCertExtType:
+ switch (id) {
+ case BASIC_CA_OID:
+ oid = extBasicCaOid;
+ *oidSz = sizeof(extBasicCaOid);
+ break;
+ case ALT_NAMES_OID:
+ oid = extAltNamesOid;
+ *oidSz = sizeof(extAltNamesOid);
+ break;
+ case CRL_DIST_OID:
+ oid = extCrlDistOid;
+ *oidSz = sizeof(extCrlDistOid);
+ break;
+ case AUTH_INFO_OID:
+ oid = extAuthInfoOid;
+ *oidSz = sizeof(extAuthInfoOid);
+ break;
+ case AUTH_KEY_OID:
+ oid = extAuthKeyOid;
+ *oidSz = sizeof(extAuthKeyOid);
+ break;
+ case SUBJ_KEY_OID:
+ oid = extSubjKeyOid;
+ *oidSz = sizeof(extSubjKeyOid);
+ break;
+ case CERT_POLICY_OID:
+ oid = extCertPolicyOid;
+ *oidSz = sizeof(extCertPolicyOid);
+ break;
+ case KEY_USAGE_OID:
+ oid = extKeyUsageOid;
+ *oidSz = sizeof(extKeyUsageOid);
+ break;
+ case INHIBIT_ANY_OID:
+ oid = extInhibitAnyOid;
+ *oidSz = sizeof(extInhibitAnyOid);
+ break;
+ case EXT_KEY_USAGE_OID:
+ oid = extExtKeyUsageOid;
+ *oidSz = sizeof(extExtKeyUsageOid);
+ break;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ case NAME_CONS_OID:
+ oid = extNameConsOid;
+ *oidSz = sizeof(extNameConsOid);
+ break;
+ #endif
+ }
+ break;
+
+ case oidCrlExtType:
+ #ifdef HAVE_CRL
+ switch (id) {
+ case AUTH_KEY_OID:
+ oid = extAuthKeyOid;
+ *oidSz = sizeof(extAuthKeyOid);
+ break;
+ }
+ #endif
+ break;
+
+ case oidCertAuthInfoType:
+ switch (id) {
+ #ifdef HAVE_OCSP
+ case AIA_OCSP_OID:
+ oid = extAuthInfoOcspOid;
+ *oidSz = sizeof(extAuthInfoOcspOid);
+ break;
+ #endif
+ case AIA_CA_ISSUER_OID:
+ oid = extAuthInfoCaIssuerOid;
+ *oidSz = sizeof(extAuthInfoCaIssuerOid);
+ break;
+ }
+ break;
+
+ case oidCertPolicyType:
+ switch (id) {
+ case CP_ANY_OID:
+ oid = extCertPolicyAnyOid;
+ *oidSz = sizeof(extCertPolicyAnyOid);
+ break;
+ }
+ break;
+
+ case oidCertAltNameType:
+ switch (id) {
+ case HW_NAME_OID:
+ oid = extAltNamesHwNameOid;
+ *oidSz = sizeof(extAltNamesHwNameOid);
+ break;
+ }
+ break;
+
+ case oidCertKeyUseType:
+ switch (id) {
+ case EKU_ANY_OID:
+ oid = extExtKeyUsageAnyOid;
+ *oidSz = sizeof(extExtKeyUsageAnyOid);
+ break;
+ case EKU_SERVER_AUTH_OID:
+ oid = extExtKeyUsageServerAuthOid;
+ *oidSz = sizeof(extExtKeyUsageServerAuthOid);
+ break;
+ case EKU_CLIENT_AUTH_OID:
+ oid = extExtKeyUsageClientAuthOid;
+ *oidSz = sizeof(extExtKeyUsageClientAuthOid);
+ break;
+ case EKU_CODESIGNING_OID:
+ oid = extExtKeyUsageCodeSigningOid;
+ *oidSz = sizeof(extExtKeyUsageCodeSigningOid);
+ break;
+ case EKU_EMAILPROTECT_OID:
+ oid = extExtKeyUsageEmailProtectOid;
+ *oidSz = sizeof(extExtKeyUsageEmailProtectOid);
+ break;
+ case EKU_TIMESTAMP_OID:
+ oid = extExtKeyUsageTimestampOid;
+ *oidSz = sizeof(extExtKeyUsageTimestampOid);
+ break;
+ case EKU_OCSP_SIGN_OID:
+ oid = extExtKeyUsageOcspSignOid;
+ *oidSz = sizeof(extExtKeyUsageOcspSignOid);
+ break;
+ }
+ break;
+
+ case oidKdfType:
+ switch (id) {
+ case PBKDF2_OID:
+ oid = pbkdf2Oid;
+ *oidSz = sizeof(pbkdf2Oid);
+ break;
+ }
+ break;
+
+ case oidPBEType:
+ switch (id) {
+ #if !defined(NO_SHA) && !defined(NO_RC4)
+ case PBE_SHA1_RC4_128:
+ oid = pbeSha1RC4128;
+ *oidSz = sizeof(pbeSha1RC4128);
+ break;
+ #endif
+ #if !defined(NO_SHA) && !defined(NO_DES3)
+ case PBE_SHA1_DES:
+ oid = pbeSha1Des;
+ *oidSz = sizeof(pbeSha1Des);
+ break;
+
+ #endif
+ #if !defined(NO_SHA) && !defined(NO_DES3)
+ case PBE_SHA1_DES3:
+ oid = pbeSha1Des3;
+ *oidSz = sizeof(pbeSha1Des3);
+ break;
+ #endif
+ case PBES2:
+ oid = pbes2;
+ *oidSz = sizeof(pbes2);
+ break;
+ }
+ break;
+
+ case oidKeyWrapType:
+ switch (id) {
+ #ifdef WOLFSSL_AES_128
+ case AES128_WRAP:
+ oid = wrapAes128Oid;
+ *oidSz = sizeof(wrapAes128Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_192
+ case AES192_WRAP:
+ oid = wrapAes192Oid;
+ *oidSz = sizeof(wrapAes192Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_AES_256
+ case AES256_WRAP:
+ oid = wrapAes256Oid;
+ *oidSz = sizeof(wrapAes256Oid);
+ break;
+ #endif
+ #ifdef HAVE_PKCS7
+ case PWRI_KEK_WRAP:
+ oid = wrapPwriKekOid;
+ *oidSz = sizeof(wrapPwriKekOid);
+ break;
+ #endif
+ }
+ break;
+
+ case oidCmsKeyAgreeType:
+ switch (id) {
+ #ifndef NO_SHA
+ case dhSinglePass_stdDH_sha1kdf_scheme:
+ oid = dhSinglePass_stdDH_sha1kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha1kdf_Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case dhSinglePass_stdDH_sha224kdf_scheme:
+ oid = dhSinglePass_stdDH_sha224kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha224kdf_Oid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case dhSinglePass_stdDH_sha256kdf_scheme:
+ oid = dhSinglePass_stdDH_sha256kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha256kdf_Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case dhSinglePass_stdDH_sha384kdf_scheme:
+ oid = dhSinglePass_stdDH_sha384kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha384kdf_Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case dhSinglePass_stdDH_sha512kdf_scheme:
+ oid = dhSinglePass_stdDH_sha512kdf_Oid;
+ *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid);
+ break;
+ #endif
+ }
+ break;
+
+#ifndef NO_HMAC
+ case oidHmacType:
+ switch (id) {
+ #ifdef WOLFSSL_SHA224
+ case HMAC_SHA224_OID:
+ oid = hmacSha224Oid;
+ *oidSz = sizeof(hmacSha224Oid);
+ break;
+ #endif
+ #ifndef NO_SHA256
+ case HMAC_SHA256_OID:
+ oid = hmacSha256Oid;
+ *oidSz = sizeof(hmacSha256Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case HMAC_SHA384_OID:
+ oid = hmacSha384Oid;
+ *oidSz = sizeof(hmacSha384Oid);
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA512
+ case HMAC_SHA512_OID:
+ oid = hmacSha512Oid;
+ *oidSz = sizeof(hmacSha512Oid);
+ break;
+ #endif
+ }
+ break;
+#endif /* !NO_HMAC */
+
+#ifdef HAVE_LIBZ
+ case oidCompressType:
+ switch (id) {
+ case ZLIBc:
+ oid = zlibCompress;
+ *oidSz = sizeof(zlibCompress);
+ break;
+ }
+ break;
+#endif /* HAVE_LIBZ */
+#ifdef WOLFSSL_APACHE_HTTPD
+ case oidCertNameType:
+ switch (id) {
+ case NID_id_on_dnsSRV:
+ oid = dnsSRVOid;
+ *oidSz = sizeof(dnsSRVOid);
+ break;
+ }
+ break;
+ case oidTlsExtType:
+ switch (id) {
+ case TLS_FEATURE_OID:
+ oid = tlsFeatureOid;
+ *oidSz = sizeof(tlsFeatureOid);
+ break;
+ }
+ break;
+#endif /* WOLFSSL_APACHE_HTTPD */
+ case oidIgnoreType:
+ default:
+ break;
+ }
+
+ return oid;
+}
+
+#ifdef HAVE_OID_ENCODING
+int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz)
+{
+ int i, x, len;
+ word32 d, t;
+
+ /* check args */
+ if (in == NULL || outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* compute length of encoded OID */
+ d = (in[0] * 40) + in[1];
+ len = 0;
+ for (i = 1; i < (int)inSz; i++) {
+ x = 0;
+ t = d;
+ while (t) {
+ x++;
+ t >>= 1;
+ }
+ len += (x / 7) + ((x % 7) ? 1 : 0) + (d == 0 ? 1 : 0);
+
+ if (i < (int)inSz - 1) {
+ d = in[i + 1];
+ }
+ }
+
+ if (out) {
+ /* verify length */
+ if ((int)*outSz < len) {
+ return BUFFER_E; /* buffer provided is not large enough */
+ }
+
+ /* calc first byte */
+ d = (in[0] * 40) + in[1];
+
+ /* encode bytes */
+ x = 0;
+ for (i = 1; i < (int)inSz; i++) {
+ if (d) {
+ int y = x, z;
+ byte mask = 0;
+ while (d) {
+ out[x++] = (byte)((d & 0x7F) | mask);
+ d >>= 7;
+ mask |= 0x80; /* upper bit is set on all but the last byte */
+ }
+ /* now swap bytes y...x-1 */
+ z = x - 1;
+ while (y < z) {
+ mask = out[y];
+ out[y] = out[z];
+ out[z] = mask;
+ ++y;
+ --z;
+ }
+ }
+ else {
+ out[x++] = 0x00; /* zero value */
+ }
+
+ /* next word */
+ if (i < (int)inSz - 1) {
+ d = in[i + 1];
+ }
+ }
+ }
+
+ /* return length */
+ *outSz = len;
+
+ return 0;
+}
+#endif /* HAVE_OID_ENCODING */
+
+#ifdef HAVE_OID_DECODING
+int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz)
+{
+ int x = 0, y = 0;
+ word32 t = 0;
+
+ /* check args */
+ if (in == NULL || outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* decode bytes */
+ while (inSz--) {
+ t = (t << 7) | (in[x] & 0x7F);
+ if (!(in[x] & 0x80)) {
+ if (y >= (int)*outSz) {
+ return BUFFER_E;
+ }
+ if (y == 0) {
+ out[0] = (t / 40);
+ out[1] = (t % 40);
+ y = 2;
+ }
+ else {
+ out[y++] = t;
+ }
+ t = 0; /* reset tmp */
+ }
+ x++;
+ }
+
+ /* return length */
+ *outSz = y;
+
+ return 0;
+}
+#endif /* HAVE_OID_DECODING */
+
+/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header.
+ *
+ * input Buffer holding DER/BER encoded data.
+ * inOutIdx Current index into buffer to parse.
+ * len The number of bytes in the ASN.1 data.
+ * maxIdx Length of data in buffer.
+ * returns BUFFER_E when there is not enough data to parse.
+ * ASN_OBJECt_ID_E when the OBJECT_ID tag is not found.
+ * ASN_PARSE_E when length is invalid.
+ * Otherwise, 0 to indicate success.
+ */
+int GetASNObjectId(const byte* input, word32* inOutIdx, int* len,
+ word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
int length;
+ byte tag;
- if (b != ASN_INTEGER)
+ if ((idx + 1) > maxIdx)
+ return BUFFER_E;
+
+ if (GetASNTag(input, &idx, &tag, maxIdx) != 0)
return ASN_PARSE_E;
- if (GetLength(input, &i, &length, maxIdx) < 0)
+ if (tag != ASN_OBJECT_ID)
+ return ASN_OBJECT_ID_E;
+
+ if (GetLength(input, &idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
- if ( (b = input[i++]) == 0x00)
- length--;
- else
- i--;
+ *len = length;
+ *inOutIdx = idx;
+ return 0;
+}
- *buffSz = (word16)length;
- *buff = XMALLOC(*buffSz, heap, DYNAMIC_TYPE_CAVIUM_RSA);
- if (*buff == NULL)
- return MEMORY_E;
+/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header.
+ *
+ * len Length of the OBJECT_ID data.
+ * output Buffer to write into.
+ * returns the number of bytes added to the buffer.
+ */
+int SetObjectId(int len, byte* output)
+{
+ int idx = 0;
+
+ output[idx++] = ASN_OBJECT_ID;
+ idx += SetLength(len, output + idx);
- XMEMCPY(*buff, input + i, *buffSz);
+ return idx;
+}
+
+int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
+ word32 oidType, word32 maxIdx)
+{
+ int ret = 0, length;
+ word32 idx = *inOutIdx;
+#ifndef NO_VERIFY_OID
+ word32 actualOidSz = 0;
+ const byte* actualOid;
+#endif /* NO_VERIFY_OID */
+
+ (void)oidType;
+ WOLFSSL_ENTER("GetObjectId()");
+ *oid = 0;
+
+ ret = GetASNObjectId(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
+
+#ifndef NO_VERIFY_OID
+ actualOid = &input[idx];
+ if (length > 0)
+ actualOidSz = (word32)length;
+#endif /* NO_VERIFY_OID */
+
+ while (length--) {
+ /* odd HC08 compiler behavior here when input[idx++] */
+ *oid += (word32)input[idx];
+ idx++;
+ }
+ /* just sum it up for now */
+
+ *inOutIdx = idx;
+
+#ifndef NO_VERIFY_OID
+ {
+ const byte* checkOid = NULL;
+ word32 checkOidSz;
+ #ifdef ASN_DUMP_OID
+ word32 i;
+ #endif
+
+ if (oidType != oidIgnoreType) {
+ checkOid = OidFromId(*oid, oidType, &checkOidSz);
+
+ #ifdef ASN_DUMP_OID
+ /* support for dumping OID information */
+ printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid);
+ for (i=0; i<actualOidSz; i++) {
+ printf("%d, ", actualOid[i]);
+ }
+ printf("\n");
+ #ifdef HAVE_OID_DECODING
+ {
+ word16 decOid[16];
+ word32 decOidSz = sizeof(decOid);
+ ret = DecodeObjectId(actualOid, actualOidSz, decOid, &decOidSz);
+ if (ret == 0) {
+ printf(" Decoded (Sz %d): ", decOidSz);
+ for (i=0; i<decOidSz; i++) {
+ printf("%d.", decOid[i]);
+ }
+ printf("\n");
+ }
+ else {
+ printf("DecodeObjectId failed: %d\n", ret);
+ }
+ }
+ #endif /* HAVE_OID_DECODING */
+ #endif /* ASN_DUMP_OID */
+
+ if (checkOid != NULL &&
+ (checkOidSz != actualOidSz ||
+ XMEMCMP(actualOid, checkOid, checkOidSz) != 0)) {
+ WOLFSSL_MSG("OID Check Failed");
+ return ASN_UNKNOWN_OID_E;
+ }
+ }
+ }
+#endif /* NO_VERIFY_OID */
+
+ return ret;
+}
+
+static int SkipObjectId(const byte* input, word32* inOutIdx, word32 maxIdx)
+{
+ word32 idx = *inOutIdx;
+ int length;
+ int ret;
+
+ ret = GetASNObjectId(input, &idx, &length, maxIdx);
+ if (ret != 0)
+ return ret;
+
+ idx += length;
+ *inOutIdx = idx;
- *inOutIdx = i + length;
return 0;
}
-static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
- RsaKey* key, word32 inSz)
+int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
+ word32 oidType, word32 maxIdx)
{
- int version, length;
- void* h = key->heap;
+ int length;
+ word32 idx = *inOutIdx;
+ int ret;
+ *oid = 0;
- if (GetSequence(input, inOutIdx, &length, inSz) < 0)
- return ASN_PARSE_E;
+ WOLFSSL_ENTER("GetAlgoId");
- if (GetMyVersion(input, inOutIdx, &version) < 0)
+ if (GetSequence(input, &idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
- key->type = RSA_PRIVATE;
+ if (GetObjectId(input, &idx, oid, oidType, maxIdx) < 0)
+ return ASN_OBJECT_ID_E;
- if (GetCaviumInt(&key->c_n, &key->c_nSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_e, &key->c_eSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_d, &key->c_dSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_p, &key->c_pSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_q, &key->c_qSz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 ||
- GetCaviumInt(&key->c_u, &key->c_uSz, input, inOutIdx, inSz, h) < 0 )
- return ASN_RSA_KEY_E;
+ /* could have NULL tag and 0 terminator, but may not */
+ if (idx < maxIdx) {
+ word32 localIdx = idx; /*use localIdx to not advance when checking tag*/
+ byte tag;
+
+ if (GetASNTag(input, &localIdx, &tag, maxIdx) == 0) {
+ if (tag == ASN_TAG_NULL) {
+ ret = GetASNNull(input, &idx, maxIdx);
+ if (ret != 0)
+ return ret;
+ }
+ }
+ }
+
+ *inOutIdx = idx;
return 0;
}
+#ifndef NO_RSA
-#endif /* HAVE_CAVIUM */
-
+#ifndef HAVE_USER_RSA
int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
word32 inSz)
{
- int version, length;
-
-#ifdef HAVE_CAVIUM
- if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
- return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz);
-#endif
+ int version, length;
+ if (inOutIdx == NULL) {
+ return BAD_FUNC_ARG;
+ }
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, inOutIdx, &version) < 0)
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
return ASN_PARSE_E;
key->type = RSA_PRIVATE;
if (GetInt(&key->n, input, inOutIdx, inSz) < 0 ||
GetInt(&key->e, input, inOutIdx, inSz) < 0 ||
+#ifndef WOLFSSL_RSA_PUBLIC_ONLY
GetInt(&key->d, input, inOutIdx, inSz) < 0 ||
GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->q, input, inOutIdx, inSz) < 0)
+#else
+ SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 )
+
+#endif
+ return ASN_RSA_KEY_E;
+#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)) \
+ && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
+ if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 ||
GetInt(&key->dQ, input, inOutIdx, inSz) < 0 ||
GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
+#else
+ if (SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 ||
+ SkipInt(input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
+#endif
+
+#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL)
+ if (wc_InitRsaHw(key) != 0) {
+ return BAD_STATE_E;
+ }
+#endif
return 0;
}
-
+#endif /* HAVE_USER_RSA */
#endif /* NO_RSA */
-/* Remove PKCS8 header, move beginning of traditional to beginning of input */
-int ToTraditional(byte* input, word32 sz)
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+
+/* Remove PKCS8 header, place inOutIdx at beginning of traditional,
+ * return traditional length on success, negative on error */
+int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz,
+ word32* algId)
{
- word32 inOutIdx = 0, oid;
+ word32 idx;
int version, length;
+ int ret;
+ byte tag;
+
+ if (input == NULL || inOutIdx == NULL)
+ return BAD_FUNC_ARG;
+
+ idx = *inOutIdx;
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
+ if (GetSequence(input, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetMyVersion(input, &idx, &version, sz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, &inOutIdx, &version) < 0)
+ if (GetAlgoId(input, &idx, algId, oidKeyType, sz) < 0)
return ASN_PARSE_E;
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
+ if (GetASNTag(input, &idx, &tag, sz) < 0)
return ASN_PARSE_E;
+ idx = idx - 1; /* reset idx after finding tag */
- if (input[inOutIdx] == ASN_OBJECT_ID) {
- /* pkcs8 ecc uses slightly different format */
- inOutIdx++; /* past id */
- if (GetLength(input, &inOutIdx, &length, sz) < 0)
+ if (tag == ASN_OBJECT_ID) {
+ if (SkipObjectId(input, &idx, sz) < 0)
return ASN_PARSE_E;
- inOutIdx += length; /* over sub id, key input will verify */
}
- if (input[inOutIdx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
+ ret = GetOctetString(input, &idx, &length, sz);
+ if (ret < 0) {
+ if (ret == BUFFER_E)
+ return ASN_PARSE_E;
+ /* Some private keys don't expect an octet string */
+ WOLFSSL_MSG("Couldn't find Octet string");
+ }
- if (GetLength(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ *inOutIdx = idx;
+
+ return length;
+}
+
+int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz)
+{
+ word32 oid;
+
+ return ToTraditionalInline_ex(input, inOutIdx, sz, &oid);
+}
+
+/* Remove PKCS8 header, move beginning of traditional to beginning of input */
+int ToTraditional_ex(byte* input, word32 sz, word32* algId)
+{
+ word32 inOutIdx = 0;
+ int length;
+
+ if (input == NULL)
+ return BAD_FUNC_ARG;
+
+ length = ToTraditionalInline_ex(input, &inOutIdx, sz, algId);
+ if (length < 0)
+ return length;
XMEMMOVE(input, input + inOutIdx, length);
return length;
}
+int ToTraditional(byte* input, word32 sz)
+{
+ word32 oid;
+
+ return ToTraditional_ex(input, sz, &oid);
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
+
+/* find beginning of traditional key inside PKCS#8 unencrypted buffer
+ * return traditional length on success, with inOutIdx at beginning of
+ * traditional
+ * return negative on failure/error */
+int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz)
+{
+ int length;
+ word32 algId;
+
+ if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz))
+ return BAD_FUNC_ARG;
+
+ length = ToTraditionalInline_ex(input, inOutIdx, sz, &algId);
+
+ return length;
+}
+
+
+/* PKCS#8 from RFC 5208
+ * This function takes in a DER key and converts it to PKCS#8 format. Used
+ * in creating PKCS#12 shrouded key bags.
+ * Reverse of ToTraditional
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes optional
+ * }
+ * Version ::= INTEGER
+ * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ * PrivateKey ::= OCTET STRING
+ *
+ * out buffer to place result in
+ * outSz size of out buffer
+ * key buffer with DER key
+ * keySz size of key buffer
+ * algoID algorithm ID i.e. RSAk
+ * curveOID ECC curve oid if used. Should be NULL for RSA keys.
+ * oidSz size of curve oid. Is set to 0 if curveOID is NULL.
+ *
+ * Returns the size of PKCS#8 placed into out. In error cases returns negative
+ * values.
+ */
+int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz,
+ int algoID, const byte* curveOID, word32 oidSz)
+{
+ word32 keyIdx = 0;
+ word32 tmpSz = 0;
+ word32 sz;
+
+
+ /* If out is NULL then return the max size needed
+ * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */
+ if (out == NULL && outSz != NULL) {
+ *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+ + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2;
+
+ if (curveOID != NULL)
+ *outSz += oidSz + MAX_LENGTH_SZ + 1;
+
+ WOLFSSL_MSG("Checking size of PKCS8");
+
+ return LENGTH_ONLY_E;
+ }
+
+ WOLFSSL_ENTER("wc_CreatePKCS8Key()");
+
+ if (key == NULL || out == NULL || outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* check the buffer has enough room for largest possible size */
+ if (curveOID != NULL) {
+ if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+ + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ))
+ return BUFFER_E;
+ }
+ else {
+ oidSz = 0; /* with no curveOID oid size must be 0 */
+ if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ
+ + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2))
+ return BUFFER_E;
+ }
+
+ /* PrivateKeyInfo ::= SEQUENCE */
+ keyIdx += MAX_SEQ_SZ; /* save room for sequence */
+
+ /* version Version
+ * no header information just INTEGER */
+ sz = SetMyVersion(PKCS8v0, out + keyIdx, 0);
+ tmpSz += sz; keyIdx += sz;
+
+ /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */
+ sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */
+ if (curveOID != NULL && oidSz > 0) {
+ byte buf[MAX_LENGTH_SZ];
+ sz = SetLength(oidSz, buf);
+ sz += 1; /* plus one for ASN object id */
+ }
+ sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz);
+ tmpSz += sz; keyIdx += sz;
+
+ /* privateKey PrivateKey *
+ * pkcs8 ecc uses slightly different format. Places curve oid in
+ * buffer */
+ if (curveOID != NULL && oidSz > 0) {
+ sz = SetObjectId(oidSz, out + keyIdx);
+ keyIdx += sz; tmpSz += sz;
+ XMEMCPY(out + keyIdx, curveOID, oidSz);
+ keyIdx += oidSz; tmpSz += oidSz;
+ }
+
+ sz = SetOctetString(keySz, out + keyIdx);
+ keyIdx += sz; tmpSz += sz;
+ XMEMCPY(out + keyIdx, key, keySz);
+ tmpSz += keySz;
+
+ /* attributes optional
+ * No attributes currently added */
+
+ /* rewind and add sequence */
+ sz = SetSequence(tmpSz, out);
+ XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz);
+
+ return tmpSz + sz;
+}
+
+#endif /* HAVE_PKCS8 */
+
+#if defined(HAVE_PKCS12) || !defined(NO_CHECK_PRIVATE_KEY)
+/* check that the private key is a pair for the public key in certificate
+ * return 1 (true) on match
+ * return 0 or negative value on failure/error
+ *
+ * key : buffer holding DER format key
+ * keySz : size of key buffer
+ * der : a initialized and parsed DecodedCert holding a certificate */
+int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der)
+{
+ int ret;
+ (void)keySz;
+
+ if (key == NULL || der == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
+ /* test if RSA key */
+ if (der->keyOID == RSAk) {
+ #ifdef WOLFSSL_SMALL_STACK
+ RsaKey* a;
+ RsaKey* b = NULL;
+ #else
+ RsaKey a[1], b[1];
+ #endif
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ a = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+ if (a == NULL)
+ return MEMORY_E;
+ b = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
+ if (b == NULL) {
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ return MEMORY_E;
+ }
+ #endif
+
+ if ((ret = wc_InitRsaKey(a, NULL)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_InitRsaKey(b, NULL)) < 0) {
+ wc_FreeRsaKey(a);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 0) {
+ WOLFSSL_MSG("Checking RSA key pair");
+ keyIdx = 0; /* reset to 0 for parsing public key */
+
+ if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, b,
+ der->pubKeySize)) == 0) {
+ /* limit for user RSA crypto because of RsaKey
+ * dereference. */
+ #if defined(HAVE_USER_RSA)
+ WOLFSSL_MSG("Cannot verify RSA pair with user RSA");
+ ret = 1; /* return first RSA cert as match */
+ #else
+ /* both keys extracted successfully now check n and e
+ * values are the same. This is dereferencing RsaKey */
+ if (mp_cmp(&(a->n), &(b->n)) != MP_EQ ||
+ mp_cmp(&(a->e), &(b->e)) != MP_EQ) {
+ ret = MP_CMP_E;
+ }
+ else
+ ret = 1;
+ #endif
+ }
+ }
+ wc_FreeRsaKey(b);
+ wc_FreeRsaKey(a);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(b, NULL, DYNAMIC_TYPE_RSA);
+ XFREE(a, NULL, DYNAMIC_TYPE_RSA);
+ #endif
+ }
+ else
+ #endif /* !NO_RSA && !NO_ASN_CRYPT */
+
+ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT)
+ if (der->keyOID == ECDSAk) {
+ #ifdef WOLFSSL_SMALL_STACK
+ ecc_key* key_pair;
+ byte* privDer;
+ #else
+ ecc_key key_pair[1];
+ byte privDer[MAX_ECC_BYTES];
+ #endif
+ word32 privSz = MAX_ECC_BYTES;
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ key_pair = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC);
+ if (key_pair == NULL)
+ return MEMORY_E;
+ privDer = (byte*)XMALLOC(MAX_ECC_BYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (privDer == NULL) {
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+ return MEMORY_E;
+ }
+ #endif
+
+ if ((ret = wc_ecc_init(key_pair)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+ #endif
+ return ret;
+ }
+
+ if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair,
+ keySz)) == 0) {
+ WOLFSSL_MSG("Checking ECC key pair");
+
+ if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz))
+ == 0) {
+ wc_ecc_free(key_pair);
+ ret = wc_ecc_init(key_pair);
+ if (ret == 0) {
+ ret = wc_ecc_import_private_key((const byte*)privDer,
+ privSz, (const byte*)der->publicKey,
+ der->pubKeySize, key_pair);
+ }
+
+ /* public and private extracted successfully now check if is
+ * a pair and also do sanity checks on key. wc_ecc_check_key
+ * checks that private * base generator equals pubkey */
+ if (ret == 0) {
+ if ((ret = wc_ecc_check_key(key_pair)) == 0) {
+ ret = 1;
+ }
+ }
+ ForceZero(privDer, privSz);
+ }
+ }
+ wc_ecc_free(key_pair);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC);
+ #endif
+ }
+ else
+ #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */
+
+ #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
+ if (der->keyOID == ED25519k) {
+ #ifdef WOLFSSL_SMALL_STACK
+ ed25519_key* key_pair;
+ #else
+ ed25519_key key_pair[1];
+ #endif
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ key_pair = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL,
+ DYNAMIC_TYPE_ED25519);
+ if (key_pair == NULL)
+ return MEMORY_E;
+ #endif
+
+ if ((ret = wc_ed25519_init(key_pair)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair,
+ keySz)) == 0) {
+ WOLFSSL_MSG("Checking ED25519 key pair");
+ keyIdx = 0;
+ if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize,
+ key_pair)) == 0) {
+ /* public and private extracted successfully no check if is
+ * a pair and also do sanity checks on key. wc_ecc_check_key
+ * checks that private * base generator equals pubkey */
+ if ((ret = wc_ed25519_check_key(key_pair)) == 0)
+ ret = 1;
+ }
+ }
+ wc_ed25519_free(key_pair);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519);
+ #endif
+ }
+ else
+ #endif /* HAVE_ED25519 && !NO_ASN_CRYPT */
+
+ #if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
+ if (der->keyOID == ED448k) {
+ #ifdef WOLFSSL_SMALL_STACK
+ ed448_key* key_pair = NULL;
+ #else
+ ed448_key key_pair[1];
+ #endif
+ word32 keyIdx = 0;
+
+ #ifdef WOLFSSL_SMALL_STACK
+ key_pair = (ed448_key*)XMALLOC(sizeof(ed448_key), NULL,
+ DYNAMIC_TYPE_ED448);
+ if (key_pair == NULL)
+ return MEMORY_E;
+ #endif
+
+ if ((ret = wc_ed448_init(key_pair)) < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448);
+ #endif
+ return ret;
+ }
+ if ((ret = wc_Ed448PrivateKeyDecode(key, &keyIdx, key_pair,
+ keySz)) == 0) {
+ WOLFSSL_MSG("Checking ED448 key pair");
+ keyIdx = 0;
+ if ((ret = wc_ed448_import_public(der->publicKey, der->pubKeySize,
+ key_pair)) == 0) {
+ /* public and private extracted successfully no check if is
+ * a pair and also do sanity checks on key. wc_ecc_check_key
+ * checks that private * base generator equals pubkey */
+ if ((ret = wc_ed448_check_key(key_pair)) == 0)
+ ret = 1;
+ }
+ }
+ wc_ed448_free(key_pair);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(key_pair, NULL, DYNAMIC_TYPE_ED448);
+ #endif
+ }
+ else
+ #endif /* HAVE_ED448 && !NO_ASN_CRYPT */
+ {
+ ret = 0;
+ }
+
+ (void)keySz;
+
+ return ret;
+}
+
+#endif /* HAVE_PKCS12 || !NO_CHECK_PRIVATE_KEY */
#ifndef NO_PWDBASED
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
/* Check To see if PKCS version algo is supported, set id if it is return 0
< 0 on error */
-static int CheckAlgo(int first, int second, int* id, int* version)
+static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz)
{
*id = ALGO_ID_E;
*version = PKCS5; /* default */
+ if (blockSz) *blockSz = 8; /* default */
if (first == 1) {
switch (second) {
- case 1:
+#if !defined(NO_SHA)
+ #ifndef NO_RC4
+ case PBE_SHA1_RC4_128:
*id = PBE_SHA1_RC4_128;
- *version = PKCS12;
+ *version = PKCS12v1;
return 0;
- case 3:
+ #endif
+ #ifndef NO_DES3
+ case PBE_SHA1_DES3:
*id = PBE_SHA1_DES3;
- *version = PKCS12;
+ *version = PKCS12v1;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+ case PBE_SHA1_DES:
+ *id = PBE_SHA1_DES;
+ *version = PKCS12v1;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
+ return 0;
+ #endif
+#endif /* !NO_SHA */
default:
return ALGO_ID_E;
}
@@ -857,213 +3124,655 @@ static int CheckAlgo(int first, int second, int* id, int* version)
}
switch (second) {
+#ifndef NO_DES3
+ #ifndef NO_MD5
case 3: /* see RFC 2898 for ids */
*id = PBE_MD5_DES;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+ #endif
+ #ifndef NO_SHA
case 10:
*id = PBE_SHA1_DES;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+ #endif
+#endif /* !NO_DES3 */
default:
return ALGO_ID_E;
}
}
-
/* Check To see if PKCS v2 algo is supported, set id if it is return 0
< 0 on error */
-static int CheckAlgoV2(int oid, int* id)
+static int CheckAlgoV2(int oid, int* id, int* blockSz)
{
+ if (blockSz) *blockSz = 8; /* default */
+ (void)id; /* not used if AES and DES3 disabled */
switch (oid) {
- case 69:
+#if !defined(NO_DES3) && !defined(NO_SHA)
+ case DESb:
*id = PBE_SHA1_DES;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
- case 652:
+ case DES3b:
*id = PBE_SHA1_DES3;
+ if (blockSz) *blockSz = DES_BLOCK_SIZE;
return 0;
+#endif
+#ifdef WOLFSSL_AES_256
+ case AES256CBCb:
+ *id = PBE_AES256_CBC;
+ if (blockSz) *blockSz = AES_BLOCK_SIZE;
+ return 0;
+#endif
+#ifdef WOLFSSL_AES_128
+ case AES128CBCb:
+ *id = PBE_AES128_CBC;
+ if (blockSz) *blockSz = AES_BLOCK_SIZE;
+ return 0;
+#endif
default:
+ WOLFSSL_MSG("No PKCS v2 algo found");
return ALGO_ID_E;
}
}
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
-/* Decrypt intput in place from parameters based on id */
-static int DecryptKey(const char* password, int passwordSz, byte* salt,
- int saltSz, int iterations, int id, byte* input,
- int length, int version, byte* cbcIv)
+int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz,
+ int* algoID, void* heap)
{
- int typeH;
- int derivedLen;
- int decryptionType;
- int ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
- byte* key;
-#else
- byte key[MAX_KEY_SIZE];
-#endif
+ word32 tmpIdx = 0;
- switch (id) {
- case PBE_MD5_DES:
- typeH = MD5;
- derivedLen = 16; /* may need iv for v1.5 */
- decryptionType = DES_TYPE;
- break;
+ if (key == NULL || algoID == NULL)
+ return BAD_FUNC_ARG;
- case PBE_SHA1_DES:
- typeH = SHA;
- derivedLen = 16; /* may need iv for v1.5 */
- decryptionType = DES_TYPE;
- break;
+ *algoID = 0;
- case PBE_SHA1_DES3:
- typeH = SHA;
- derivedLen = 32; /* may need iv for v1.5 */
- decryptionType = DES3_TYPE;
- break;
+ #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
+ {
+ RsaKey rsa;
- case PBE_SHA1_RC4_128:
- typeH = SHA;
- derivedLen = 16;
- decryptionType = RC4_TYPE;
- break;
+ wc_InitRsaKey(&rsa, heap);
+ if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) {
+ *algoID = RSAk;
+ }
+ else {
+ WOLFSSL_MSG("Not RSA DER key");
+ }
+ wc_FreeRsaKey(&rsa);
+ }
+ #endif /* !NO_RSA && !NO_ASN_CRYPT */
+ #if defined(HAVE_ECC) && !defined(NO_ASN_CRYPT)
+ if (*algoID == 0) {
+ ecc_key ecc;
+
+ tmpIdx = 0;
+ wc_ecc_init_ex(&ecc, heap, INVALID_DEVID);
+ if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) {
+ *algoID = ECDSAk;
+
+ /* now find oid */
+ if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) {
+ WOLFSSL_MSG("Error getting ECC curve OID");
+ wc_ecc_free(&ecc);
+ return BAD_FUNC_ARG;
+ }
+ }
+ else {
+ WOLFSSL_MSG("Not ECC DER key either");
+ }
+ wc_ecc_free(&ecc);
+ }
+#endif /* HAVE_ECC && !NO_ASN_CRYPT */
+#if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
+ if (*algoID != RSAk && *algoID != ECDSAk) {
+ ed25519_key ed25519;
+
+ tmpIdx = 0;
+ if (wc_ed25519_init(&ed25519) == 0) {
+ if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz)
+ == 0) {
+ *algoID = ED25519k;
+ }
+ else {
+ WOLFSSL_MSG("Not ED25519 DER key");
+ }
+ wc_ed25519_free(&ed25519);
+ }
+ else {
+ WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed");
+ }
+ }
+#endif /* HAVE_ED25519 && !NO_ASN_CRYPT */
+#if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
+ if (*algoID != RSAk && *algoID != ECDSAk && *algoID != ED25519k) {
+ ed448_key ed448;
+
+ tmpIdx = 0;
+ if (wc_ed448_init(&ed448) == 0) {
+ if (wc_Ed448PrivateKeyDecode(key, &tmpIdx, &ed448, keySz) == 0) {
+ *algoID = ED448k;
+ }
+ else {
+ WOLFSSL_MSG("Not ED448 DER key");
+ }
+ wc_ed448_free(&ed448);
+ }
+ else {
+ WOLFSSL_MSG("GetKeyOID wc_ed448_init failed");
+ }
+ }
+#endif /* HAVE_ED448 && !NO_ASN_CRYPT */
- default:
- return ALGO_ID_E;
+ /* if flag is not set then is neither RSA or ECC key that could be
+ * found */
+ if (*algoID == 0) {
+ WOLFSSL_MSG("Bad key DER or compile options");
+ return BAD_FUNC_ARG;
}
-#ifdef WOLFSSL_SMALL_STACK
- key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (key == NULL)
- return MEMORY_E;
-#endif
+ (void)tmpIdx;
+ (void)curveOID;
+ (void)oidSz;
+ (void)keySz;
+ (void)heap;
- if (version == PKCS5v2)
- ret = wc_PBKDF2(key, (byte*)password, passwordSz, salt, saltSz, iterations,
- derivedLen, typeH);
-#ifndef NO_SHA
- else if (version == PKCS5)
- ret = wc_PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations,
- derivedLen, typeH);
-#endif
- else if (version == PKCS12) {
- int i, idx = 0;
- byte unicodePasswd[MAX_UNICODE_SZ];
+ return 1;
+}
+
+#endif /* HAVE_PKCS8 */
+
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+
+#define PKCS8_MIN_BLOCK_SIZE 8
+static int Pkcs8Pad(byte* buf, int sz, int blockSz)
+{
+ int i, padSz;
+
+ /* calculate pad size */
+ padSz = blockSz - (sz & (blockSz - 1));
+
+ /* pad with padSz value */
+ if (buf) {
+ for (i = 0; i < padSz; i++) {
+ buf[sz+i] = (byte)(padSz & 0xFF);
+ }
+ }
+
+ /* return adjusted length */
+ return sz + padSz;
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS8
+
+/*
+ * Used when creating PKCS12 shrouded key bags
+ * vPKCS is the version of PKCS to use
+ * vAlgo is the algorithm version to use
+ *
+ * if salt is NULL a random number is generated
+ *
+ * returns the size of encrypted data on success
+ */
+int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
+ const char* password, int passwordSz, int vPKCS, int vAlgo,
+ byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
+{
+ int algoID = 0;
+ byte* tmp;
+ word32 tmpSz = 0;
+ word32 sz;
+ word32 seqSz;
+ word32 inOutIdx = 0;
+ word32 totalSz = 0;
+ int version, id;
+ int ret;
+ int blockSz = 0;
+
+ const byte* curveOID = NULL;
+ word32 oidSz = 0;
- if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* saltTmp = NULL;
+ byte* cbcIv = NULL;
+#else
+ byte saltTmp[MAX_IV_SIZE];
+ byte cbcIv[MAX_IV_SIZE];
#endif
- return UNICODE_SIZE_E;
+
+ WOLFSSL_ENTER("UnTraditionalEnc()");
+
+ if (saltSz > MAX_SALT_SIZE)
+ return ASN_PARSE_E;
+
+
+ inOutIdx += MAX_SEQ_SZ; /* leave room for size of finished shroud */
+ if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) {
+ WOLFSSL_MSG("Bad/Unsupported algorithm ID");
+ return ASN_INPUT_E; /* Algo ID error */
+ }
+
+ if (out != NULL) {
+ if (*outSz < inOutIdx + MAX_ALGO_SZ + MAX_SALT_SIZE + MAX_SEQ_SZ + 1 +
+ MAX_LENGTH_SZ + MAX_SHORT_SZ + 1)
+ return BUFFER_E;
+
+ if (version == PKCS5v2) {
+ WOLFSSL_MSG("PKCS5v2 Not supported yet\n");
+ return ASN_VERSION_E;
}
- for (i = 0; i < passwordSz; i++) {
- unicodePasswd[idx++] = 0x00;
- unicodePasswd[idx++] = (byte)password[i];
+ if (salt == NULL || saltSz == 0) {
+ saltSz = 8;
+ #ifdef WOLFSSL_SMALL_STACK
+ saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp == NULL)
+ return MEMORY_E;
+ #endif
+ salt = saltTmp;
+
+ if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+ WOLFSSL_MSG("Error generating random salt");
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
}
- /* add trailing NULL */
- unicodePasswd[idx++] = 0x00;
- unicodePasswd[idx++] = 0x00;
- ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz,
- iterations, derivedLen, typeH, 1);
- if (decryptionType != RC4_TYPE)
- ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz,
- iterations, 8, typeH, 2);
+
+ /* leave room for a sequence (contains salt and iterations int) */
+ inOutIdx += MAX_SEQ_SZ; sz = 0;
+ inOutIdx += MAX_ALGO_SZ;
+
+ /* place salt in buffer */
+ out[inOutIdx++] = ASN_OCTET_STRING; sz++;
+ tmpSz = SetLength(saltSz, out + inOutIdx);
+ inOutIdx += tmpSz; sz += tmpSz;
+ XMEMCPY(out + inOutIdx, salt, saltSz);
+ inOutIdx += saltSz; sz += saltSz;
+
+ /* place iteration count in buffer */
+ ret = SetShortInt(out, &inOutIdx, itt, *outSz);
+ if (ret < 0) {
+ return ret;
+ }
+ sz += (word32)ret;
+
+ /* wind back index and set sequence then clean up buffer */
+ inOutIdx -= (sz + MAX_SEQ_SZ);
+ tmpSz = SetSequence(sz, out + inOutIdx);
+ XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_SEQ_SZ, sz);
+ totalSz += tmpSz + sz; sz += tmpSz;
+
+ /* add in algo ID */
+ inOutIdx -= MAX_ALGO_SZ;
+ tmpSz = SetAlgoID(id, out + inOutIdx, oidPBEType, sz);
+ XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_ALGO_SZ, sz);
+ totalSz += tmpSz; inOutIdx += tmpSz + sz;
+
+ /* octet string containing encrypted key */
+ out[inOutIdx++] = ASN_OCTET_STRING; totalSz++;
}
- else {
+
+ /* check key type and get OID if ECC */
+ if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) {
+ WOLFSSL_MSG("Error getting key OID");
+ return ret;
+ }
+
+ /* PKCS#8 wrapping around key */
+ if (wc_CreatePKCS8Key(NULL, &tmpSz, key, keySz, algoID, curveOID, oidSz)
+ != LENGTH_ONLY_E) {
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return MEMORY_E;
+ }
+
+ /* check if should return max size */
+ if (out == NULL) {
+ /* account for salt size */
+ if (salt == NULL || saltSz == 0) {
+ tmpSz += MAX_SALT_SIZE;
+ }
+ else {
+ tmpSz += saltSz;
+ }
+
+ /* plus 3 for tags */
+ *outSz = tmpSz + MAX_ALGO_SZ + MAX_LENGTH_SZ +MAX_LENGTH_SZ + MAX_SEQ_SZ
+ + MAX_LENGTH_SZ + MAX_SEQ_SZ + 3;
+ return LENGTH_ONLY_E;
+ }
+
+ /* reserve buffer for crypto and make sure it supports full blocks */
+ tmp = (byte*)XMALLOC(tmpSz + (blockSz-1), heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmp == NULL) {
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return MEMORY_E;
+ }
+
+ if ((ret = wc_CreatePKCS8Key(tmp, &tmpSz, key, keySz, algoID, curveOID,
+ oidSz)) < 0) {
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_MSG("Error wrapping key with PKCS#8");
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
+ tmpSz = ret;
+
+ /* adjust size to pad */
+ tmpSz = Pkcs8Pad(tmp, tmpSz, blockSz);
+
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv == NULL) {
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(salt, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
- return ALGO_ID_E;
+
+ /* encrypt PKCS#8 wrapped key */
+ if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+ tmp, tmpSz, version, cbcIv, 1, 0)) < 0) {
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_MSG("Error encrypting key");
+ #ifdef WOLFSSL_SMALL_STACK
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv != NULL)
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret; /* encryption failure */
}
+ totalSz += tmpSz;
- if (ret != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp != NULL)
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv != NULL)
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return ret;
+
+ if (*outSz < inOutIdx + tmpSz + MAX_LENGTH_SZ) {
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return BUFFER_E;
}
- switch (decryptionType) {
-#ifndef NO_DES3
- case DES_TYPE:
- {
- Des dec;
- byte* desIv = key + 8;
+ /* set length of key and copy over encrypted key */
+ seqSz = SetLength(tmpSz, out + inOutIdx);
+ inOutIdx += seqSz; totalSz += seqSz;
+ XMEMCPY(out + inOutIdx, tmp, tmpSz);
+ XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (version == PKCS5v2 || version == PKCS12)
- desIv = cbcIv;
+ /* set total size at beginning */
+ sz = SetSequence(totalSz, out);
+ XMEMMOVE(out + sz, out + MAX_SEQ_SZ, totalSz);
- ret = wc_Des_SetKey(&dec, key, desIv, DES_DECRYPTION);
- if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ret;
- }
+ (void)rng;
- wc_Des_CbcDecrypt(&dec, input, input, length);
- break;
- }
+ return totalSz + sz;
+}
- case DES3_TYPE:
- {
- Des3 dec;
- byte* desIv = key + 24;
+static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id,
+ int *blkSz)
+{
+ int ret = 0;
- if (version == PKCS5v2 || version == PKCS12)
- desIv = cbcIv;
- ret = wc_Des3_SetKey(&dec, key, desIv, DES_DECRYPTION);
- if (ret != 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ switch (encAlgId) {
+#if !defined(NO_DES3) && !defined(NO_SHA)
+ case DESb:
+ *len = sizeof(blkDesCbcOid);
+ *oid = blkDesCbcOid;
+ *id = PBE_SHA1_DES;
+ *blkSz = 8;
+ break;
+ case DES3b:
+ *len = sizeof(blkDes3CbcOid);
+ *oid = blkDes3CbcOid;
+ *id = PBE_SHA1_DES3;
+ *blkSz = 8;
+ break;
#endif
- return ret;
- }
- ret = wc_Des3_CbcDecrypt(&dec, input, input, length);
- if (ret != 0) {
+#if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC)
+ case AES256CBCb:
+ *len = sizeof(blkAes256CbcOid);
+ *oid = blkAes256CbcOid;
+ *id = PBE_AES256_CBC;
+ *blkSz = 16;
+ break;
+#endif
+ default:
+ (void)len;
+ (void)oid;
+ (void)id;
+ (void)blkSz;
+ ret = ALGO_ID_E;
+ }
+
+ return ret;
+}
+
+/* Converts Encrypted PKCS#8 to 'traditional' (i.e. PKCS#8 removed from
+ * decrypted key.)
+ */
+int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz,
+ const char* password, int passwordSz, int vPKCS, int vAlgo,
+ int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng,
+ void* heap)
+{
+ int ret = 0;
+ int version, blockSz, id;
+ word32 idx = 0, encIdx;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* saltTmp = NULL;
+#else
+ byte saltTmp[MAX_SALT_SIZE];
#endif
- return ret;
- }
- break;
+ byte cbcIv[MAX_IV_SIZE];
+ byte *pkcs8Key = NULL;
+ word32 pkcs8KeySz = 0, padSz = 0;
+ int algId = 0;
+ const byte* curveOid = NULL;
+ word32 curveOidSz = 0;
+ const byte* pbeOid = NULL;
+ word32 pbeOidSz = 0;
+ const byte* encOid = NULL;
+ int encOidSz = 0;
+ word32 pbeLen = 0, kdfLen = 0, encLen = 0;
+ word32 innerLen = 0, outerLen;
+
+ ret = CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz);
+ /* create random salt if one not provided */
+ if (ret == 0 && (salt == NULL || saltSz == 0)) {
+ saltSz = 8;
+ #ifdef WOLFSSL_SMALL_STACK
+ saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp == NULL)
+ return MEMORY_E;
+ #endif
+ salt = saltTmp;
+
+ if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+ WOLFSSL_MSG("Error generating random salt");
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
}
-#endif
-#ifndef NO_RC4
- case RC4_TYPE:
- {
- Arc4 dec;
+ }
- wc_Arc4SetKey(&dec, key, derivedLen);
- wc_Arc4Process(&dec, input, input, length);
- break;
+ if (ret == 0) {
+ /* check key type and get OID if ECC */
+ ret = wc_GetKeyOID(key, keySz, &curveOid, &curveOidSz, &algId, heap);
+ if (ret == 1)
+ ret = 0;
+ }
+ if (ret == 0) {
+ ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid,
+ curveOidSz);
+ if (ret == LENGTH_ONLY_E)
+ ret = 0;
+ }
+ if (ret == 0) {
+ pkcs8Key = (byte*)XMALLOC(pkcs8KeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pkcs8Key == NULL)
+ ret = MEMORY_E;
+ }
+ if (ret == 0) {
+ ret = wc_CreatePKCS8Key(pkcs8Key, &pkcs8KeySz, key, keySz, algId,
+ curveOid, curveOidSz);
+ if (ret >= 0) {
+ pkcs8KeySz = ret;
+ ret = 0;
}
-#endif
+ }
- default:
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ALGO_ID_E;
+ if (ret == 0 && version == PKCS5v2)
+ ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &id, &blockSz);
+
+ if (ret == 0) {
+ padSz = (blockSz - (pkcs8KeySz & (blockSz - 1))) & (blockSz - 1);
+ /* inner = OCT salt INT itt */
+ innerLen = 2 + saltSz + 2 + (itt < 256 ? 1 : 2);
+
+ if (version != PKCS5v2) {
+ pbeOid = OidFromId(id, oidPBEType, &pbeOidSz);
+ /* pbe = OBJ pbse1 SEQ [ inner ] */
+ pbeLen = 2 + pbeOidSz + 2 + innerLen;
+ }
+ else {
+ pbeOid = pbes2;
+ pbeOidSz = sizeof(pbes2);
+ /* kdf = OBJ pbkdf2 [ SEQ innerLen ] */
+ kdfLen = 2 + sizeof(pbkdf2Oid) + 2 + innerLen;
+ /* enc = OBJ enc_alg OCT iv */
+ encLen = 2 + encOidSz + 2 + blockSz;
+ /* pbe = OBJ pbse2 SEQ [ SEQ [ kdf ] SEQ [ enc ] ] */
+ pbeLen = 2 + sizeof(pbes2) + 2 + 2 + kdfLen + 2 + encLen;
+
+ ret = wc_RNG_GenerateBlock(rng, cbcIv, blockSz);
+ }
+ }
+ if (ret == 0) {
+ /* outer = SEQ [ pbe ] OCT encrypted_PKCS#8_key */
+ outerLen = 2 + pbeLen;
+ outerLen += SetOctetString(pkcs8KeySz + padSz, out);
+ outerLen += pkcs8KeySz + padSz;
+
+ idx += SetSequence(outerLen, out + idx);
+
+ encIdx = idx + outerLen - pkcs8KeySz - padSz;
+ /* Put Encrypted content in place. */
+ XMEMCPY(out + encIdx, pkcs8Key, pkcs8KeySz);
+ if (padSz > 0) {
+ XMEMSET(out + encIdx + pkcs8KeySz, padSz, padSz);
+ pkcs8KeySz += padSz;
+ }
+ ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+ out + encIdx, pkcs8KeySz, version, cbcIv, 1, 0);
+ }
+ if (ret == 0) {
+ if (version != PKCS5v2) {
+ /* PBE algorithm */
+ idx += SetSequence(pbeLen, out + idx);
+ idx += SetObjectId(pbeOidSz, out + idx);
+ XMEMCPY(out + idx, pbeOid, pbeOidSz);
+ idx += pbeOidSz;
+ }
+ else {
+ /* PBES2 algorithm identifier */
+ idx += SetSequence(pbeLen, out + idx);
+ idx += SetObjectId(pbeOidSz, out + idx);
+ XMEMCPY(out + idx, pbeOid, pbeOidSz);
+ idx += pbeOidSz;
+ /* PBES2 Parameters: SEQ [ kdf ] SEQ [ enc ] */
+ idx += SetSequence(2 + kdfLen + 2 + encLen, out + idx);
+ /* KDF Algorithm Identifier */
+ idx += SetSequence(kdfLen, out + idx);
+ idx += SetObjectId(sizeof(pbkdf2Oid), out + idx);
+ XMEMCPY(out + idx, pbkdf2Oid, sizeof(pbkdf2Oid));
+ idx += sizeof(pbkdf2Oid);
+ }
+ idx += SetSequence(innerLen, out + idx);
+ idx += SetOctetString(saltSz, out + idx);
+ XMEMCPY(out + idx, salt, saltSz); idx += saltSz;
+ ret = SetShortInt(out, &idx, itt, *outSz);
+ if (ret > 0)
+ ret = 0;
+ }
+ if (ret == 0) {
+ if (version == PKCS5v2) {
+ /* Encryption Algorithm Identifier */
+ idx += SetSequence(encLen, out + idx);
+ idx += SetObjectId(encOidSz, out + idx);
+ XMEMCPY(out + idx, encOid, encOidSz);
+ idx += encOidSz;
+ /* Encryption Algorithm Parameter: CBC IV */
+ idx += SetOctetString(blockSz, out + idx);
+ XMEMCPY(out + idx, cbcIv, blockSz);
+ idx += blockSz;
+ }
+ idx += SetOctetString(pkcs8KeySz, out + idx);
+ /* Default PRF - no need to write out OID */
+ idx += pkcs8KeySz;
+
+ ret = idx;
}
+ if (pkcs8Key != NULL) {
+ ForceZero(pkcs8Key, pkcs8KeySz);
+ XFREE(pkcs8Key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
#ifdef WOLFSSL_SMALL_STACK
- XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp != NULL) {
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
#endif
- return 0;
+ (void)rng;
+
+ return ret;
}
+#endif /* HAVE_PKCS8 */
-/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
- of input */
-int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+/* decrypt PKCS
+ *
+ * NOTE: input buffer is overwritten with decrypted data!
+ *
+ * input[in/out] data to decrypt and results are written to
+ * sz size of input buffer
+ * password password if used. Can be NULL for no password
+ * passwordSz size of password buffer
+ *
+ * returns the total size of decrypted content on success.
+ */
+int DecryptContent(byte* input, word32 sz, const char* password, int passwordSz)
{
- word32 inOutIdx = 0, oid;
- int first, second, length, version, saltSz, id;
- int iterations = 0;
+ word32 inOutIdx = 0, seqEnd, oid, shaOid = 0;
+ int ret = 0, first, second, length = 0, version, saltSz, id;
+ int iterations = 0, keySz = 0;
#ifdef WOLFSSL_SMALL_STACK
byte* salt = NULL;
byte* cbcIv = NULL;
@@ -1071,205 +3780,560 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
byte salt[MAX_SALT_SIZE];
byte cbcIv[MAX_IV_SIZE];
#endif
-
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ byte tag;
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
- return ASN_PARSE_E;
-
- first = input[inOutIdx - 2]; /* PKCS version alwyas 2nd to last byte */
+ if (passwordSz < 0) {
+ WOLFSSL_MSG("Bad password size");
+ return BAD_FUNC_ARG;
+ }
+
+ if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */
second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
- if (CheckAlgo(first, second, &id, &version) < 0)
- return ASN_INPUT_E; /* Algo ID error */
+ if (CheckAlgo(first, second, &id, &version, NULL) < 0) {
+ ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */
+ }
if (version == PKCS5v2) {
+ if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0)
- return ASN_PARSE_E;
+ if (oid != PBKDF2_OID) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+ }
- if (oid != PBKDF2_OID)
- return ASN_PARSE_E;
+ if (GetSequence(input, &inOutIdx, &length, sz) <= 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
}
+ /* Find the end of this SEQUENCE so we can check for the OPTIONAL and
+ * DEFAULT items. */
+ seqEnd = inOutIdx + length;
- if (GetSequence(input, &inOutIdx, &length, sz) < 0)
- return ASN_PARSE_E;
+ ret = GetOctetString(input, &inOutIdx, &saltSz, sz);
+ if (ret < 0)
+ goto exit_dc;
- if (input[inOutIdx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
-
- if (GetLength(input, &inOutIdx, &saltSz, sz) < 0)
- return ASN_PARSE_E;
+ if (saltSz > MAX_SALT_SIZE) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
- if (saltSz > MAX_SALT_SIZE)
- return ASN_PARSE_E;
-
#ifdef WOLFSSL_SMALL_STACK
salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (salt == NULL)
- return MEMORY_E;
+ if (salt == NULL) {
+ ERROR_OUT(MEMORY_E, exit_dc);
+ }
#endif
XMEMCPY(salt, &input[inOutIdx], saltSz);
inOutIdx += saltSz;
- if (GetShortInt(input, &inOutIdx, &iterations) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
+ if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ /* OPTIONAL key length */
+ if (seqEnd > inOutIdx) {
+ word32 localIdx = inOutIdx;
+
+ if (GetASNTag(input, &localIdx, &tag, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ if (tag == ASN_INTEGER &&
+ GetShortInt(input, &inOutIdx, &keySz, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+ }
+
+ /* DEFAULT HMAC is SHA-1 */
+ if (seqEnd > inOutIdx) {
+ if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ shaOid = oid;
}
#ifdef WOLFSSL_SMALL_STACK
cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (cbcIv == NULL) {
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+ ERROR_OUT(MEMORY_E, exit_dc);
}
#endif
if (version == PKCS5v2) {
/* get encryption algo */
- if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
+ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
}
- if (CheckAlgoV2(oid, &id) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E; /* PKCS v2 algo id error */
+ if (CheckAlgoV2(oid, &id, NULL) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */
}
- if (input[inOutIdx++] != ASN_OCTET_STRING) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &inOutIdx, &length, sz) < 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- return ASN_PARSE_E;
+ if (shaOid == 0)
+ shaOid = oid;
+
+ ret = GetOctetString(input, &inOutIdx, &length, sz);
+ if (ret < 0)
+ goto exit_dc;
+
+ if (length > MAX_IV_SIZE) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
}
XMEMCPY(cbcIv, &input[inOutIdx], length);
inOutIdx += length;
}
- if (input[inOutIdx++] != ASN_OCTET_STRING) {
+ if (GetASNTag(input, &inOutIdx, &tag, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | 0) && tag != ASN_OCTET_STRING) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ if (GetLength(input, &inOutIdx, &length, sz) < 0) {
+ ERROR_OUT(ASN_PARSE_E, exit_dc);
+ }
+
+ ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id,
+ input + inOutIdx, length, version, cbcIv, 0, shaOid);
+
+exit_dc:
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return ASN_PARSE_E;
+
+ if (ret == 0) {
+ XMEMMOVE(input, input + inOutIdx, length);
+ ret = length;
}
- if (GetLength(input, &inOutIdx, &length, sz) < 0) {
+ return ret;
+}
+
+
+/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning
+ of input */
+int ToTraditionalEnc(byte* input, word32 sz,const char* password,
+ int passwordSz, word32* algId)
+{
+ int ret, length;
+ word32 inOutIdx = 0;
+
+ if (GetSequence(input, &inOutIdx, &length, sz) < 0) {
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = DecryptContent(input + inOutIdx, sz - inOutIdx, password,
+ passwordSz);
+ if (ret > 0) {
+ XMEMMOVE(input, input + inOutIdx, ret);
+ ret = ToTraditional_ex(input, ret, algId);
+ }
+ }
+
+ return ret;
+}
+
+#endif /* HAVE_PKCS8 || HAVE_PKCS12 */
+
+#ifdef HAVE_PKCS12
+
+/* encrypt PKCS 12 content
+ *
+ * NOTE: if out is NULL then outSz is set with the total buffer size needed and
+ * the error value LENGTH_ONLY_E is returned.
+ *
+ * input data to encrypt
+ * inputSz size of input buffer
+ * out buffer to hold the result
+ * outSz size of out buffer
+ * password password if used. Can be NULL for no password
+ * passwordSz size of password buffer
+ * vPKCS version of PKCS i.e. PKCS5v2
+ * vAlgo algorithm version
+ * salt buffer holding salt if used. If NULL then a random salt is created
+ * saltSz size of salt buffer if it is not NULL
+ * itt number of iterations used
+ * rng random number generator to use
+ * heap possible heap hint for mallocs/frees
+ *
+ * returns the total size of encrypted content on success.
+ *
+ * data returned is :
+ * [ seq - obj [ seq -salt,itt]] , construct with encrypted data
+ */
+int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
+ const char* password, int passwordSz, int vPKCS, int vAlgo,
+ byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
+{
+ word32 sz;
+ word32 inOutIdx = 0;
+ word32 tmpIdx = 0;
+ word32 totalSz = 0;
+ word32 seqSz;
+ word32 innerSz;
+ int ret;
+ int version, id, blockSz = 0;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* saltTmp = NULL;
+ byte* cbcIv = NULL;
+#else
+ byte saltTmp[MAX_SALT_SIZE];
+ byte cbcIv[MAX_IV_SIZE];
#endif
+ byte seq[MAX_SEQ_SZ];
+ byte shr[MAX_SHORT_SZ];
+ word32 maxShr = MAX_SHORT_SZ;
+ word32 algoSz;
+ const byte* algoName;
+
+ (void)heap;
+
+ WOLFSSL_ENTER("EncryptContent()");
+
+ if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0)
+ return ASN_INPUT_E; /* Algo ID error */
+
+ if (version == PKCS5v2) {
+ WOLFSSL_MSG("PKCS#5 version 2 not supported yet");
+ return BAD_FUNC_ARG;
+ }
+
+ if (saltSz > MAX_SALT_SIZE)
return ASN_PARSE_E;
+
+ if (outSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* calculate size */
+ /* size of constructed string at end */
+ sz = Pkcs8Pad(NULL, inputSz, blockSz);
+ totalSz = ASN_TAG_SZ;
+ totalSz += SetLength(sz, seq);
+ totalSz += sz;
+
+ /* size of sequence holding object id and sub sequence of salt and itt */
+ algoName = OidFromId(id, oidPBEType, &algoSz);
+ if (algoName == NULL) {
+ WOLFSSL_MSG("Unknown Algorithm");
+ return 0;
+ }
+ innerSz = SetObjectId(algoSz, seq);
+ innerSz += algoSz;
+
+ /* get subsequence of salt and itt */
+ if (salt == NULL || saltSz == 0) {
+ sz = 8;
+ }
+ else {
+ sz = saltSz;
+ }
+ seqSz = SetOctetString(sz, seq);
+ seqSz += sz;
+
+ tmpIdx = 0;
+ seqSz += SetShortInt(shr, &tmpIdx, itt, maxShr);
+ innerSz += seqSz + SetSequence(seqSz, seq);
+ totalSz += innerSz + SetSequence(innerSz, seq);
+
+ if (out == NULL) {
+ *outSz = totalSz;
+ return LENGTH_ONLY_E;
+ }
+
+ inOutIdx = 0;
+ if (totalSz > *outSz)
+ return BUFFER_E;
+
+ inOutIdx += SetSequence(innerSz, out + inOutIdx);
+ inOutIdx += SetObjectId(algoSz, out + inOutIdx);
+ XMEMCPY(out + inOutIdx, algoName, algoSz);
+ inOutIdx += algoSz;
+ inOutIdx += SetSequence(seqSz, out + inOutIdx);
+
+ /* create random salt if one not provided */
+ if (salt == NULL || saltSz == 0) {
+ saltSz = 8;
+ #ifdef WOLFSSL_SMALL_STACK
+ saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (saltTmp == NULL)
+ return MEMORY_E;
+ #endif
+ salt = saltTmp;
+
+ if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
+ WOLFSSL_MSG("Error generating random salt");
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
+ }
+ inOutIdx += SetOctetString(saltSz, out + inOutIdx);
+ if (saltSz + inOutIdx > *outSz) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
}
+ XMEMCPY(out + inOutIdx, salt, saltSz);
+ inOutIdx += saltSz;
- if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id,
- input + inOutIdx, length, version, cbcIv) < 0) {
+ /* place iteration setting in buffer */
+ ret = SetShortInt(out, &inOutIdx, itt, *outSz);
+ if (ret < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret;
+ }
+
+ if (inOutIdx + 1 > *outSz) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+ out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0;
+
+ /* get pad size and verify buffer room */
+ sz = Pkcs8Pad(NULL, inputSz, blockSz);
+ if (sz + inOutIdx > *outSz) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+ inOutIdx += SetLength(sz, out + inOutIdx);
+
+ /* copy input to output buffer and pad end */
+ XMEMCPY(out + inOutIdx, input, inputSz);
+ sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz);
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (cbcIv == NULL) {
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
- return ASN_INPUT_E; /* decrypt failure */
+
+ /* encrypt */
+ if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
+ out + inOutIdx, sz, version, cbcIv, 1, 0)) < 0) {
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return ret; /* encrypt failure */
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- XMEMMOVE(input, input + inOutIdx, length);
- return ToTraditional(input, length);
+ (void)rng;
+
+ return inOutIdx + sz;
}
+
+#endif /* HAVE_PKCS12 */
#endif /* NO_PWDBASED */
#ifndef NO_RSA
-int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
- word32 inSz)
+#ifndef HAVE_USER_RSA
+#ifdef WOLFSSL_RENESAS_TSIP
+/* This function is to retrieve key position information in a cert.*
+ * The information will be used to call TSIP TLS-linked API for *
+ * certificate verification. */
+static int RsaPublicKeyDecodeRawIndex(const byte* input, word32* inOutIdx,
+ word32 inSz, word32* key_n,
+ word32* key_n_len, word32* key_e,
+ word32* key_e_len)
{
- int length;
+
+ int ret = 0;
+ int length = 0;
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ byte b;
+#endif
+
+ if (input == NULL || inOutIdx == NULL)
+ return BAD_FUNC_ARG;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- key->type = RSA_PUBLIC;
-
#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
- {
- byte b = input[*inOutIdx];
+ if ((*inOutIdx + 1) > inSz)
+ return BUFFER_E;
+
+ b = input[*inOutIdx];
if (b != ASN_INTEGER) {
/* not from decoded cert, will have algo id, skip past */
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
-
- b = input[(*inOutIdx)++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(input, inOutIdx, &length, inSz) < 0)
+
+ if (SkipObjectId(input, inOutIdx, inSz) < 0)
return ASN_PARSE_E;
-
- *inOutIdx += length; /* skip past */
-
- /* could have NULL tag and 0 terminator, but may not */
- b = input[(*inOutIdx)++];
-
- if (b == ASN_TAG_NULL) {
- b = input[(*inOutIdx)++];
- if (b != 0)
- return ASN_EXPECT_0_E;
+
+ /* Option NULL ASN.1 tag */
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
}
- else
- /* go back, didn't have it */
- (*inOutIdx)--;
-
+ if (input[*inOutIdx] == ASN_TAG_NULL) {
+ ret = GetASNNull(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+ }
+
/* should have bit tag length and seq next */
- b = input[(*inOutIdx)++];
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
-
- if (GetLength(input, inOutIdx, &length, inSz) < 0)
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
-
- /* could have 0 */
- b = input[(*inOutIdx)++];
- if (b != 0)
- (*inOutIdx)--;
-
+ }
+#endif /* OPENSSL_EXTRA */
+
+ /* Get modulus */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ *key_n += *inOutIdx;
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (key_n_len)
+ *key_n_len = length;
+ *inOutIdx += length;
+
+ /* Get exponent */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ *key_e += *inOutIdx;
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (key_e_len)
+ *key_e_len = length;
+
+ return ret;
+}
+#endif /* WOLFSSL_RENESAS_TSIP */
+
+int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz,
+ const byte** n, word32* nSz, const byte** e, word32* eSz)
+{
+ int ret = 0;
+ int length = 0;
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ word32 localIdx;
+ byte tag;
+#endif
+
+ if (input == NULL || inOutIdx == NULL)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA)
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) < 0)
+ return BUFFER_E;
+
+ if (tag != ASN_INTEGER) {
+ /* not from decoded cert, will have algo id, skip past */
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- } /* end if */
- } /* openssl var block */
+
+ if (SkipObjectId(input, inOutIdx, inSz) < 0)
+ return ASN_PARSE_E;
+
+ /* Option NULL ASN.1 tag */
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
+ }
+
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (tag == ASN_TAG_NULL) {
+ ret = GetASNNull(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* should have bit tag length and seq next */
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+ }
#endif /* OPENSSL_EXTRA */
- if (GetInt(&key->n, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E;
+ /* Get modulus */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (nSz)
+ *nSz = length;
+ if (n)
+ *n = &input[*inOutIdx];
+ *inOutIdx += length;
- return 0;
+ /* Get exponent */
+ ret = GetASNInt(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ return ASN_RSA_KEY_E;
+ }
+ if (eSz)
+ *eSz = length;
+ if (e)
+ *e = &input[*inOutIdx];
+ *inOutIdx += length;
+
+ return ret;
+}
+
+int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
+ word32 inSz)
+{
+ int ret;
+ const byte *n = NULL, *e = NULL;
+ word32 nSz = 0, eSz = 0;
+
+ if (key == NULL)
+ return BAD_FUNC_ARG;
+
+ ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz);
+ if (ret == 0) {
+ ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key);
+ }
+
+ return ret;
}
/* import RSA public key elements (n, e) into RsaKey structure (key) */
@@ -1288,6 +4352,12 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
mp_clear(&key->n);
return ASN_GETINT_E;
}
+#ifdef HAVE_WOLF_BIGINT
+ if ((int)nSz > 0 && wc_bigint_from_unsigned_bin(&key->n.raw, n, nSz) != 0) {
+ mp_clear(&key->n);
+ return ASN_GETINT_E;
+ }
+#endif /* HAVE_WOLF_BIGINT */
if (mp_init(&key->e) != MP_OKAY) {
mp_clear(&key->n);
@@ -1299,76 +4369,143 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e,
mp_clear(&key->e);
return ASN_GETINT_E;
}
+#ifdef HAVE_WOLF_BIGINT
+ if ((int)eSz > 0 && wc_bigint_from_unsigned_bin(&key->e.raw, e, eSz) != 0) {
+ mp_clear(&key->n);
+ mp_clear(&key->e);
+ return ASN_GETINT_E;
+ }
+#endif /* HAVE_WOLF_BIGINT */
+
+#ifdef WOLFSSL_XILINX_CRYPT
+ if (wc_InitRsaHw(key) != 0) {
+ return BAD_STATE_E;
+ }
+#endif
return 0;
}
-
-#endif
+#endif /* HAVE_USER_RSA */
+#endif /* !NO_RSA */
#ifndef NO_DH
int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
{
- int length;
+ int ret = 0;
+ int length;
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ word32 oid = 0, temp = 0;
+ #endif
+
+ WOLFSSL_ENTER("wc_DhKeyDecode");
+
+ if (inOutIdx == NULL)
+ return BAD_FUNC_ARG;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ temp = *inOutIdx;
+ #endif
+
+ /* Assume input started after 1.2.840.113549.1.3.1 dhKeyAgreement */
if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->g, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
+ GetInt(&key->g, input, inOutIdx, inSz) < 0) {
+ ret = ASN_DH_KEY_E;
+ }
- return 0;
+ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ /* If ASN_DH_KEY_E: Check if input started at beginning of key */
+ if (ret == ASN_DH_KEY_E) {
+ /* rewind back to after the first sequence */
+ *inOutIdx = temp;
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ /* Check for dhKeyAgreement */
+ ret = GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz);
+ if (oid != DHk || ret < 0)
+ return ASN_DH_KEY_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->g, input, inOutIdx, inSz) < 0) {
+ return ASN_DH_KEY_E;
+ }
+ }
+
+ temp = *inOutIdx;
+ ret = (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) == 0);
+ if (ret > 0) {
+ /* Found Bit String */
+ if (GetInt(&key->pub, input, inOutIdx, inSz) == 0) {
+ WOLFSSL_MSG("Found Public Key");
+ ret = 0;
+ }
+ } else {
+ *inOutIdx = temp;
+ ret = (GetOctetString(input, inOutIdx, &length, inSz) >= 0);
+ if (ret > 0) {
+ /* Found Octet String */
+ if (GetInt(&key->priv, input, inOutIdx, inSz) == 0) {
+ WOLFSSL_MSG("Found Private Key");
+ ret = 0;
+ }
+ } else {
+ /* Don't use length from failed CheckBitString/GetOctetString */
+ *inOutIdx = temp;
+ ret = 0;
+ }
+ }
+ #endif /* WOLFSSL_QT || OPENSSL_ALL */
+
+ WOLFSSL_MSG("wc_DhKeyDecode Success");
+
+ return ret;
}
int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
byte* g, word32* gInOutSz)
{
- word32 i = 0;
- byte b;
+ word32 idx = 0;
+ int ret;
int length;
- if (GetSequence(input, &i, &length, inSz) < 0)
- return ASN_PARSE_E;
-
- b = input[i++];
- if (b != ASN_INTEGER)
- return ASN_PARSE_E;
-
- if (GetLength(input, &i, &length, inSz) < 0)
+ if (GetSequence(input, &idx, &length, inSz) <= 0)
return ASN_PARSE_E;
- if ( (b = input[i++]) == 0x00)
- length--;
- else
- i--;
+ ret = GetASNInt(input, &idx, &length, inSz);
+ if (ret != 0)
+ return ret;
if (length <= (int)*pInOutSz) {
- XMEMCPY(p, &input[i], length);
+ XMEMCPY(p, &input[idx], length);
*pInOutSz = length;
}
- else
+ else {
return BUFFER_E;
+ }
+ idx += length;
- i += length;
-
- b = input[i++];
- if (b != ASN_INTEGER)
- return ASN_PARSE_E;
-
- if (GetLength(input, &i, &length, inSz) < 0)
- return ASN_PARSE_E;
+ ret = GetASNInt(input, &idx, &length, inSz);
+ if (ret != 0)
+ return ret;
if (length <= (int)*gInOutSz) {
- XMEMCPY(g, &input[i], length);
+ XMEMCPY(g, &input[idx], length);
*gInOutSz = length;
}
- else
+ else {
return BUFFER_E;
+ }
return 0;
}
-
#endif /* NO_DH */
@@ -1378,6 +4515,11 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
word32 inSz)
{
int length;
+ int ret = 0;
+ word32 oid;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL)
+ return BAD_FUNC_ARG;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
@@ -1385,148 +4527,431 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->y, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
+ GetInt(&key->y, input, inOutIdx, inSz) < 0 )
+ ret = ASN_DH_KEY_E;
+
+ if (ret != 0) {
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = GetObjectId(input, inOutIdx, &oid, oidIgnoreType, inSz);
+ if (ret != 0)
+ return ret;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->g, input, inOutIdx, inSz) < 0)
+ return ASN_DH_KEY_E;
+
+ if (CheckBitString(input, inOutIdx, &length, inSz, 0, NULL) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->y, input, inOutIdx, inSz) < 0 )
+ return ASN_DH_KEY_E;
+
+ ret = 0;
+ }
key->type = DSA_PUBLIC;
- return 0;
+ return ret;
}
int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
word32 inSz)
{
- int length, version;
+ int length, version, ret = 0, temp = 0;
+
+ /* Sanity checks on input */
+ if (input == NULL || inOutIdx == NULL || key == NULL) {
+ return BAD_FUNC_ARG;
+ }
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, inOutIdx, &version) < 0)
- return ASN_PARSE_E;
+ temp = (int)*inOutIdx;
- if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->y, input, inOutIdx, inSz) < 0 ||
- GetInt(&key->x, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E;
+ /* Default case expects a certificate with OctetString but no version ID */
+ ret = GetInt(&key->p, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetInt(&key->q, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetInt(&key->g, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ mp_clear(&key->g);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetOctetString(input, inOutIdx, &length, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ mp_clear(&key->g);
+ ret = ASN_PARSE_E;
+ }
+ else {
+ ret = GetInt(&key->y, input, inOutIdx, inSz);
+ if (ret < 0) {
+ mp_clear(&key->p);
+ mp_clear(&key->q);
+ mp_clear(&key->g);
+ mp_clear(&key->y);
+ ret = ASN_PARSE_E;
+ }
+ }
+ }
+ }
+ }
+ /* An alternate pass if default certificate fails parsing */
+ if (ret == ASN_PARSE_E) {
+ *inOutIdx = temp;
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->q, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->g, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->y, input, inOutIdx, inSz) < 0 ||
+ GetInt(&key->x, input, inOutIdx, inSz) < 0 )
+ return ASN_DH_KEY_E;
+ }
key->type = DSA_PRIVATE;
return 0;
}
-#endif /* NO_DSA */
+static mp_int* GetDsaInt(DsaKey* key, int idx)
+{
+ if (idx == 0)
+ return &key->p;
+ if (idx == 1)
+ return &key->q;
+ if (idx == 2)
+ return &key->g;
+ if (idx == 3)
+ return &key->y;
+ if (idx == 4)
+ return &key->x;
+
+ return NULL;
+}
+
+/* Release Tmp DSA resources */
+static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap)
+{
+ int i;
+
+ for (i = 0; i < DSA_INTS; i++)
+ XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA);
+ (void)heap;
+}
-void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap)
+#if !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN)
+/* Write a public DSA key to output */
+int wc_SetDsaPublicKey(byte* output, DsaKey* key,
+ int outLen, int with_header)
{
- cert->publicKey = 0;
- cert->pubKeySize = 0;
- cert->pubKeyStored = 0;
- cert->version = 0;
- cert->signature = 0;
- cert->subjectCN = 0;
- cert->subjectCNLen = 0;
- cert->subjectCNEnc = CTC_UTF8;
- cert->subjectCNStored = 0;
- cert->weOwnAltNames = 0;
- cert->altNames = NULL;
-#ifndef IGNORE_NAME_CONSTRAINTS
- cert->altEmailNames = NULL;
- cert->permittedNames = NULL;
- cert->excludedNames = NULL;
-#endif /* IGNORE_NAME_CONSTRAINTS */
- cert->issuer[0] = '\0';
- cert->subject[0] = '\0';
- cert->source = source; /* don't own */
- cert->srcIdx = 0;
- cert->maxIdx = inSz; /* can't go over this index */
- cert->heap = heap;
- XMEMSET(cert->serial, 0, EXTERNAL_SERIAL_SIZE);
- cert->serialSz = 0;
- cert->extensions = 0;
- cert->extensionsSz = 0;
- cert->extensionsIdx = 0;
- cert->extAuthInfo = NULL;
- cert->extAuthInfoSz = 0;
- cert->extCrlInfo = NULL;
- cert->extCrlInfoSz = 0;
- XMEMSET(cert->extSubjKeyId, 0, KEYID_SIZE);
- cert->extSubjKeyIdSet = 0;
- XMEMSET(cert->extAuthKeyId, 0, KEYID_SIZE);
- cert->extAuthKeyIdSet = 0;
- cert->extKeyUsageSet = 0;
- cert->extKeyUsage = 0;
- cert->extExtKeyUsageSet = 0;
- cert->extExtKeyUsage = 0;
- cert->isCA = 0;
-#ifdef HAVE_PKCS7
- cert->issuerRaw = NULL;
- cert->issuerRawLen = 0;
+ /* p, g, q = DSA params, y = public exponent */
+#ifdef WOLFSSL_SMALL_STACK
+ byte* p = NULL;
+ byte* g = NULL;
+ byte* q = NULL;
+ byte* y = NULL;
+#else
+ byte p[MAX_DSA_INT_SZ];
+ byte g[MAX_DSA_INT_SZ];
+ byte q[MAX_DSA_INT_SZ];
+ byte y[MAX_DSA_INT_SZ];
#endif
-#ifdef WOLFSSL_CERT_GEN
- cert->subjectSN = 0;
- cert->subjectSNLen = 0;
- cert->subjectSNEnc = CTC_UTF8;
- cert->subjectC = 0;
- cert->subjectCLen = 0;
- cert->subjectCEnc = CTC_PRINTABLE;
- cert->subjectL = 0;
- cert->subjectLLen = 0;
- cert->subjectLEnc = CTC_UTF8;
- cert->subjectST = 0;
- cert->subjectSTLen = 0;
- cert->subjectSTEnc = CTC_UTF8;
- cert->subjectO = 0;
- cert->subjectOLen = 0;
- cert->subjectOEnc = CTC_UTF8;
- cert->subjectOU = 0;
- cert->subjectOULen = 0;
- cert->subjectOUEnc = CTC_UTF8;
- cert->subjectEmail = 0;
- cert->subjectEmailLen = 0;
-#endif /* WOLFSSL_CERT_GEN */
- cert->beforeDate = NULL;
- cert->beforeDateLen = 0;
- cert->afterDate = NULL;
- cert->afterDateLen = 0;
-#ifdef OPENSSL_EXTRA
- XMEMSET(&cert->issuerName, 0, sizeof(DecodedName));
- XMEMSET(&cert->subjectName, 0, sizeof(DecodedName));
- cert->extBasicConstSet = 0;
- cert->extBasicConstCrit = 0;
- cert->extBasicConstPlSet = 0;
- cert->pathLength = 0;
- cert->extSubjAltNameSet = 0;
- cert->extSubjAltNameCrit = 0;
- cert->extAuthKeyIdCrit = 0;
- cert->extSubjKeyIdCrit = 0;
- cert->extKeyUsageCrit = 0;
- cert->extExtKeyUsageCrit = 0;
- cert->extExtKeyUsageSrc = NULL;
- cert->extExtKeyUsageSz = 0;
- cert->extExtKeyUsageCount = 0;
- cert->extAuthKeyIdSrc = NULL;
- cert->extAuthKeyIdSz = 0;
- cert->extSubjKeyIdSrc = NULL;
- cert->extSubjKeyIdSz = 0;
-#endif /* OPENSSL_EXTRA */
-#if defined(OPENSSL_EXTRA) || !defined(IGNORE_NAME_CONSTRAINTS)
- cert->extNameConstraintSet = 0;
-#endif /* OPENSSL_EXTRA || !IGNORE_NAME_CONSTRAINTS */
-#ifdef HAVE_ECC
- cert->pkCurveOID = 0;
-#endif /* HAVE_ECC */
-#ifdef WOLFSSL_SEP
- cert->deviceTypeSz = 0;
- cert->deviceType = NULL;
- cert->hwTypeSz = 0;
- cert->hwType = NULL;
- cert->hwSerialNumSz = 0;
- cert->hwSerialNum = NULL;
- #ifdef OPENSSL_EXTRA
- cert->extCertPolicySet = 0;
- cert->extCertPolicyCrit = 0;
- #endif /* OPENSSL_EXTRA */
-#endif /* WOLFSSL_SEP */
+ byte innerSeq[MAX_SEQ_SZ];
+ byte outerSeq[MAX_SEQ_SZ];
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int idx, pSz, gSz, qSz, ySz, innerSeqSz, outerSeqSz, bitStringSz = 0;
+
+ WOLFSSL_ENTER("wc_SetDsaPublicKey");
+
+ if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* p */
+#ifdef WOLFSSL_SMALL_STACK
+ p = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (p == NULL)
+ return MEMORY_E;
+#endif
+ if ((pSz = SetASNIntMP(&key->p, MAX_DSA_INT_SZ, p)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with p");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return pSz;
+ }
+
+ /* q */
+#ifdef WOLFSSL_SMALL_STACK
+ q = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (q == NULL)
+ return MEMORY_E;
+#endif
+ if ((qSz = SetASNIntMP(&key->q, MAX_DSA_INT_SZ, q)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with q");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return qSz;
+ }
+
+ /* g */
+#ifdef WOLFSSL_SMALL_STACK
+ g = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (g == NULL)
+ return MEMORY_E;
+#endif
+ if ((gSz = SetASNIntMP(&key->g, MAX_DSA_INT_SZ, g)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with g");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return gSz;
+ }
+
+ /* y */
+#ifdef WOLFSSL_SMALL_STACK
+ y = (byte*)XMALLOC(MAX_DSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (y == NULL)
+ return MEMORY_E;
+#endif
+ if ((ySz = SetASNIntMP(&key->y, MAX_DSA_INT_SZ, y)) < 0) {
+ WOLFSSL_MSG("SetASNIntMP Error with y");
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return ySz;
+ }
+
+ innerSeqSz = SetSequence(pSz + qSz + gSz, innerSeq);
+
+ /* check output size */
+ if ((innerSeqSz + pSz + qSz + gSz) > outLen) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ WOLFSSL_MSG("Error, output size smaller than outlen");
+ return BUFFER_E;
+ }
+
+ if (with_header) {
+ int algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ byte* algo = NULL;
+
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
+#else
+ byte algo[MAX_ALGO_SZ];
+#endif
+ algoSz = SetAlgoID(DSAk, algo, oidKeyType, 0);
+ bitStringSz = SetBitString(ySz, 0, bitString);
+ outerSeqSz = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz,
+ outerSeq);
+
+ idx = SetSequence(algoSz + innerSeqSz + pSz + qSz + gSz + bitStringSz +
+ ySz + outerSeqSz, output);
+
+ /* check output size */
+ if ((idx + algoSz + bitStringSz + innerSeqSz + pSz + qSz + gSz + ySz) >
+ outLen) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ WOLFSSL_MSG("Error, output size smaller than outlen");
+ return BUFFER_E;
+ }
+
+ /* outerSeq */
+ XMEMCPY(output + idx, outerSeq, outerSeqSz);
+ idx += outerSeqSz;
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ } else {
+ idx = 0;
+ }
+
+ /* innerSeq */
+ XMEMCPY(output + idx, innerSeq, innerSeqSz);
+ idx += innerSeqSz;
+ /* p */
+ XMEMCPY(output + idx, p, pSz);
+ idx += pSz;
+ /* q */
+ XMEMCPY(output + idx, q, qSz);
+ idx += qSz;
+ /* g */
+ XMEMCPY(output + idx, g, gSz);
+ idx += gSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
+ /* y */
+ XMEMCPY(output + idx, y, ySz);
+ idx += ySz;
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(p, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(q, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(g, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(y, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return idx;
+}
+
+/* Convert DSA Public key to DER format, write to output (inLen), return bytes
+ written */
+int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen)
+{
+ return wc_SetDsaPublicKey(output, key, inLen, 1);
+}
+#endif /* !HAVE_SELFTEST && WOLFSSL_KEY_GEN */
+
+/* Convert private DsaKey key to DER format, write to output (inLen),
+ return bytes written */
+int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen)
+{
+ word32 seqSz, verSz, rawLen, intTotalLen = 0;
+ word32 sizes[DSA_INTS];
+ int i, j, outLen, ret = 0, mpSz;
+
+ byte seq[MAX_SEQ_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte* tmps[DSA_INTS];
+
+ if (!key || !output)
+ return BAD_FUNC_ARG;
+
+ if (key->type != DSA_PRIVATE)
+ return BAD_FUNC_ARG;
+
+ for (i = 0; i < DSA_INTS; i++)
+ tmps[i] = NULL;
+
+ /* write all big ints from key to DER tmps */
+ for (i = 0; i < DSA_INTS; i++) {
+ mp_int* keyInt = GetDsaInt(key, i);
+
+ rawLen = mp_unsigned_bin_size(keyInt) + 1;
+ tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
+ DYNAMIC_TYPE_DSA);
+ if (tmps[i] == NULL) {
+ ret = MEMORY_E;
+ break;
+ }
+
+ mpSz = SetASNIntMP(keyInt, -1, tmps[i]);
+ if (mpSz < 0) {
+ ret = mpSz;
+ break;
+ }
+ intTotalLen += (sizes[i] = mpSz);
+ }
+
+ if (ret != 0) {
+ FreeTmpDsas(tmps, key->heap);
+ return ret;
+ }
+
+ /* make headers */
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + intTotalLen, seq);
+
+ outLen = seqSz + verSz + intTotalLen;
+ if (outLen > (int)inLen) {
+ FreeTmpDsas(tmps, key->heap);
+ return BAD_FUNC_ARG;
+ }
+
+ /* write to output */
+ XMEMCPY(output, seq, seqSz);
+ j = seqSz;
+ XMEMCPY(output + j, ver, verSz);
+ j += verSz;
+
+ for (i = 0; i < DSA_INTS; i++) {
+ XMEMCPY(output + j, tmps[i], sizes[i]);
+ j += sizes[i];
+ }
+ FreeTmpDsas(tmps, key->heap);
+
+ return outLen;
+}
+
+#endif /* NO_DSA */
+
+void InitDecodedCert(DecodedCert* cert,
+ const byte* source, word32 inSz, void* heap)
+{
+ if (cert != NULL) {
+ XMEMSET(cert, 0, sizeof(DecodedCert));
+
+ cert->subjectCNEnc = CTC_UTF8;
+ cert->issuer[0] = '\0';
+ cert->subject[0] = '\0';
+ cert->source = source; /* don't own */
+ cert->maxIdx = inSz; /* can't go over this index */
+ cert->heap = heap;
+ cert->maxPathLen = WOLFSSL_MAX_PATH_LEN;
+ #ifdef WOLFSSL_CERT_GEN
+ cert->subjectSNEnc = CTC_UTF8;
+ cert->subjectCEnc = CTC_PRINTABLE;
+ cert->subjectLEnc = CTC_UTF8;
+ cert->subjectSTEnc = CTC_UTF8;
+ cert->subjectOEnc = CTC_UTF8;
+ cert->subjectOUEnc = CTC_UTF8;
+ #endif /* WOLFSSL_CERT_GEN */
+
+ #ifndef NO_CERTS
+ InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID);
+ #endif
+ }
}
@@ -1562,10 +4987,12 @@ void FreeNameSubtrees(Base_entry* names, void* heap)
void FreeDecodedCert(DecodedCert* cert)
{
+ if (cert == NULL)
+ return;
if (cert->subjectCNStored == 1)
XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN);
if (cert->pubKeyStored == 1)
- XFREE(cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
+ XFREE((void*)cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (cert->weOwnAltNames && cert->altNames)
FreeAltNames(cert->altNames, cert->heap);
#ifndef IGNORE_NAME_CONSTRAINTS
@@ -1577,126 +5004,92 @@ void FreeDecodedCert(DecodedCert* cert)
FreeNameSubtrees(cert->excludedNames, cert->heap);
#endif /* IGNORE_NAME_CONSTRAINTS */
#ifdef WOLFSSL_SEP
- XFREE(cert->deviceType, cert->heap, 0);
- XFREE(cert->hwType, cert->heap, 0);
- XFREE(cert->hwSerialNum, cert->heap, 0);
+ XFREE(cert->deviceType, cert->heap, DYNAMIC_TYPE_X509_EXT);
+ XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT);
+ XFREE(cert->hwSerialNum, cert->heap, DYNAMIC_TYPE_X509_EXT);
#endif /* WOLFSSL_SEP */
-#ifdef OPENSSL_EXTRA
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
if (cert->issuerName.fullName != NULL)
- XFREE(cert->issuerName.fullName, NULL, DYNAMIC_TYPE_X509);
+ XFREE(cert->issuerName.fullName, cert->heap, DYNAMIC_TYPE_X509);
if (cert->subjectName.fullName != NULL)
- XFREE(cert->subjectName.fullName, NULL, DYNAMIC_TYPE_X509);
+ XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509);
#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_RENESAS_TSIP_TLS
+ if (cert->tsip_encRsaKeyIdx != NULL)
+ XFREE(cert->tsip_encRsaKeyIdx, cert->heap, DYNAMIC_TYPE_RSA);
+#endif
+#ifndef NO_CERTS
+ FreeSignatureCtx(&cert->sigCtx);
+#endif
}
-
static int GetCertHeader(DecodedCert* cert)
{
int ret = 0, len;
- byte serialTmp[EXTERNAL_SERIAL_SIZE];
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- mp_int* mpi = NULL;
-#else
- mp_int stack_mpi;
- mp_int* mpi = &stack_mpi;
-#endif
if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
return ASN_PARSE_E;
+ /* Reset the max index for the size indicated in the outer wrapper. */
+ cert->maxIdx = len + cert->srcIdx;
cert->certBegin = cert->srcIdx;
if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0)
return ASN_PARSE_E;
- cert->sigIndex = len + cert->srcIdx;
- if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version) < 0)
+ cert->sigIndex = len + cert->srcIdx;
+ if (cert->sigIndex > cert->maxIdx)
return ASN_PARSE_E;
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- mpi = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (mpi == NULL)
- return MEMORY_E;
-#endif
-
- if (GetInt(mpi, cert->source, &cert->srcIdx, cert->maxIdx) < 0) {
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version,
+ cert->sigIndex) < 0)
return ASN_PARSE_E;
- }
- len = mp_unsigned_bin_size(mpi);
- if (len < (int)sizeof(serialTmp)) {
- if ( (ret = mp_to_unsigned_bin(mpi, serialTmp)) == MP_OKAY) {
- XMEMCPY(cert->serial, serialTmp, len);
- cert->serialSz = len;
- }
- }
- mp_clear(mpi);
-
-#if defined(WOLFSSL_SMALL_STACK) && defined(USE_FAST_MATH)
- XFREE(mpi, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ if (GetSerialNumber(cert->source, &cert->srcIdx, cert->serial,
+ &cert->serialSz, cert->sigIndex) < 0)
+ return ASN_PARSE_E;
return ret;
}
#if !defined(NO_RSA)
/* Store Rsa Key, may save later, Dsa could use in future */
-static int StoreRsaKey(DecodedCert* cert)
+static int StoreRsaKey(DecodedCert* cert, word32 bitStringEnd)
{
int length;
word32 recvd = cert->srcIdx;
- if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &length, bitStringEnd) < 0)
return ASN_PARSE_E;
-
+
recvd = cert->srcIdx - recvd;
length += recvd;
while (recvd--)
cert->srcIdx--;
-
+#if defined(WOLFSSL_RENESAS_TSIP)
+ cert->sigCtx.pubkey_n_start = cert->sigCtx.pubkey_e_start = cert->srcIdx;
+#endif
cert->pubKeySize = length;
cert->publicKey = cert->source + cert->srcIdx;
cert->srcIdx += length;
return 0;
}
-#endif
-
+#endif /* !NO_RSA */
#ifdef HAVE_ECC
- /* return 0 on sucess if the ECC curve oid sum is supported */
+ /* return 0 on success if the ECC curve oid sum is supported */
static int CheckCurve(word32 oid)
{
int ret = 0;
+ word32 oidSz = 0;
- switch (oid) {
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- case ECC_160R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- case ECC_192R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- case ECC_224R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- case ECC_256R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- case ECC_384R1:
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- case ECC_521R1:
-#endif
- break;
-
- default:
- ret = ALGO_ID_E;
+ ret = wc_ecc_get_oid(oid, NULL, &oidSz);
+ if (ret < 0 || oidSz == 0) {
+ WOLFSSL_MSG("CheckCurve not found");
+ ret = ALGO_ID_E;
}
return ret;
@@ -1704,35 +5097,46 @@ static int StoreRsaKey(DecodedCert* cert)
#endif /* HAVE_ECC */
-
static int GetKey(DecodedCert* cert)
{
int length;
-#ifdef HAVE_NTRU
+#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+ int tmpLen;
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_NTRU)
int tmpIdx = cert->srcIdx;
#endif
if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
return ASN_PARSE_E;
-
- if (GetAlgoId(cert->source, &cert->srcIdx, &cert->keyOID, cert->maxIdx) < 0)
+
+#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+ tmpLen = length + 4;
+#endif
+
+ if (GetAlgoId(cert->source, &cert->srcIdx,
+ &cert->keyOID, oidKeyType, cert->maxIdx) < 0)
return ASN_PARSE_E;
switch (cert->keyOID) {
#ifndef NO_RSA
case RSAk:
{
- byte b = cert->source[cert->srcIdx++];
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
+ int ret;
- if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
- return ASN_PARSE_E;
- b = cert->source[cert->srcIdx++];
- if (b != 0x00)
- return ASN_EXPECT_0_E;
-
- return StoreRsaKey(cert);
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+
+ return StoreRsaKey(cert, cert->srcIdx + length);
}
#endif /* NO_RSA */
@@ -1744,6 +5148,7 @@ static int GetKey(DecodedCert* cert)
word16 keyLen;
word32 rc;
word32 remaining = cert->maxIdx - cert->srcIdx;
+ byte* publicKey;
#ifdef WOLFSSL_SMALL_STACK
byte* keyBlob = NULL;
#else
@@ -1757,8 +5162,8 @@ static int GetKey(DecodedCert* cert)
return ASN_NTRU_KEY_E;
#ifdef WOLFSSL_SMALL_STACK
- keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
+ keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, cert->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
if (keyBlob == NULL)
return MEMORY_E;
#endif
@@ -1767,34 +5172,35 @@ static int GetKey(DecodedCert* cert)
&keyLen, keyBlob, &next, &remaining);
if (rc != NTRU_OK) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_NTRU_KEY_E;
}
if ( (next - key) < 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_NTRU_KEY_E;
}
cert->srcIdx = tmpIdx + (int)(next - key);
- cert->publicKey = (byte*) XMALLOC(keyLen, cert->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (cert->publicKey == NULL) {
+ publicKey = (byte*)XMALLOC(keyLen, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return MEMORY_E;
}
- XMEMCPY(cert->publicKey, keyBlob, keyLen);
+ XMEMCPY(publicKey, keyBlob, keyLen);
+ cert->publicKey = publicKey;
cert->pubKeyStored = 1;
cert->pubKeySize = keyLen;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(keyBlob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return 0;
@@ -1803,40 +5209,78 @@ static int GetKey(DecodedCert* cert)
#ifdef HAVE_ECC
case ECDSAk:
{
- int oidSz = 0;
- byte b = cert->source[cert->srcIdx++];
-
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
-
- if (GetLength(cert->source,&cert->srcIdx,&oidSz,cert->maxIdx) < 0)
+ int ret;
+ byte seq[5];
+ int pubLen = length + 1 + SetLength(length, seq);
+ word32 localIdx;
+ byte* publicKey;
+ byte tag;
+
+ localIdx = cert->srcIdx;
+ if (GetASNTag(cert->source, &localIdx, &tag, cert->maxIdx) < 0)
return ASN_PARSE_E;
- while(oidSz--)
- cert->pkCurveOID += cert->source[cert->srcIdx++];
+ if (tag != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
+ if (GetObjectId(cert->source, &cert->srcIdx,
+ &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0)
+ return ASN_PARSE_E;
- if (CheckCurve(cert->pkCurveOID) < 0)
- return ECC_CURVE_OID_E;
+ if (CheckCurve(cert->pkCurveOID) < 0)
+ return ECC_CURVE_OID_E;
+
+ /* key header */
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+ }
- /* key header */
- b = cert->source[cert->srcIdx++];
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
+ publicKey = (byte*)XMALLOC(pubLen, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL)
+ return MEMORY_E;
+ XMEMCPY(publicKey, &cert->source[tmpIdx], pubLen);
+ cert->publicKey = publicKey;
+ cert->pubKeyStored = 1;
+ cert->pubKeySize = pubLen;
- if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0)
- return ASN_PARSE_E;
- b = cert->source[cert->srcIdx++];
- if (b != 0x00)
- return ASN_EXPECT_0_E;
+ cert->srcIdx = tmpIdx + pubLen;
- /* actual key, use length - 1 since ate preceding 0 */
- length -= 1;
+ return 0;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ byte* publicKey;
+ int ret;
+
+ cert->pkCurveOID = ED25519k;
- cert->publicKey = (byte*) XMALLOC(length, cert->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (cert->publicKey == NULL)
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+
+ publicKey = (byte*) XMALLOC(length, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL)
return MEMORY_E;
- XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length);
+ XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
+ cert->publicKey = publicKey;
cert->pubKeyStored = 1;
cert->pubKeySize = length;
@@ -1844,25 +5288,238 @@ static int GetKey(DecodedCert* cert)
return 0;
}
- #endif /* HAVE_ECC */
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ byte* publicKey;
+ int ret;
+
+ cert->pkCurveOID = ED448k;
+
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ #ifdef HAVE_OCSP
+ ret = CalcHashId(cert->source + cert->srcIdx, length,
+ cert->subjectKeyHash);
+ if (ret != 0)
+ return ret;
+ #endif
+
+ publicKey = (byte*) XMALLOC(length, cert->heap,
+ DYNAMIC_TYPE_PUBLIC_KEY);
+ if (publicKey == NULL)
+ return MEMORY_E;
+ XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
+ cert->publicKey = publicKey;
+ cert->pubKeyStored = 1;
+ cert->pubKeySize = length;
+
+ cert->srcIdx += length;
+
+ return 0;
+ }
+ #endif /* HAVE_ED448 */
+ #if !defined(NO_DSA) && defined(WOLFSSL_QT)
+ case DSAk:
+ {
+ int ret;
+ ret = GetSequence(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx);
+ if (ret < 0)
+ return ret;
+
+ ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+ if (ret != 0)
+ return ret;
+ ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+ if (ret != 0)
+ return ret;
+ ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
+ if (ret != 0)
+ return ret;
+
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length,
+ cert->maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ ret = GetASNInt(cert->source, &cert->srcIdx, &length, cert->maxIdx);
+ if (ret !=0)
+ return ASN_PARSE_E;
+
+ cert->publicKey = cert->source + tmpIdx;
+ cert->pubKeySize = tmpLen;
+ cert->srcIdx += length;
+ return 0;
+ }
+ #endif /* NO_DSA && QT */
default:
return ASN_UNKNOWN_OID_E;
}
}
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+#if defined(HAVE_ECC)
+/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
+ value */
+WOLFSSL_API int EccEnumToNID(int n)
+{
+ WOLFSSL_ENTER("EccEnumToNID()");
+
+ switch(n) {
+ case ECC_SECP192R1:
+ return NID_X9_62_prime192v1;
+ case ECC_PRIME192V2:
+ return NID_X9_62_prime192v2;
+ case ECC_PRIME192V3:
+ return NID_X9_62_prime192v3;
+ case ECC_PRIME239V1:
+ return NID_X9_62_prime239v1;
+ case ECC_PRIME239V2:
+ return NID_X9_62_prime239v2;
+ case ECC_PRIME239V3:
+ return NID_X9_62_prime239v3;
+ case ECC_SECP256R1:
+ return NID_X9_62_prime256v1;
+ case ECC_SECP112R1:
+ return NID_secp112r1;
+ case ECC_SECP112R2:
+ return NID_secp112r2;
+ case ECC_SECP128R1:
+ return NID_secp128r1;
+ case ECC_SECP128R2:
+ return NID_secp128r2;
+ case ECC_SECP160R1:
+ return NID_secp160r1;
+ case ECC_SECP160R2:
+ return NID_secp160r2;
+ case ECC_SECP224R1:
+ return NID_secp224r1;
+ case ECC_SECP384R1:
+ return NID_secp384r1;
+ case ECC_SECP521R1:
+ return NID_secp521r1;
+ case ECC_SECP160K1:
+ return NID_secp160k1;
+ case ECC_SECP192K1:
+ return NID_secp192k1;
+ case ECC_SECP224K1:
+ return NID_secp224k1;
+ case ECC_SECP256K1:
+ return NID_secp256k1;
+ case ECC_BRAINPOOLP160R1:
+ return NID_brainpoolP160r1;
+ case ECC_BRAINPOOLP192R1:
+ return NID_brainpoolP192r1;
+ case ECC_BRAINPOOLP224R1:
+ return NID_brainpoolP224r1;
+ case ECC_BRAINPOOLP256R1:
+ return NID_brainpoolP256r1;
+ case ECC_BRAINPOOLP320R1:
+ return NID_brainpoolP320r1;
+ case ECC_BRAINPOOLP384R1:
+ return NID_brainpoolP384r1;
+ case ECC_BRAINPOOLP512R1:
+ return NID_brainpoolP512r1;
+ default:
+ WOLFSSL_MSG("NID not found");
+ return -1;
+ }
+}
+#endif /* HAVE_ECC */
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
+
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+int wc_OBJ_sn2nid(const char *sn)
+{
+ const struct {
+ const char *sn;
+ int nid;
+ } sn2nid[] = {
+ {WOLFSSL_COMMON_NAME, NID_commonName},
+ {WOLFSSL_COUNTRY_NAME, NID_countryName},
+ {WOLFSSL_LOCALITY_NAME, NID_localityName},
+ {WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
+ {WOLFSSL_ORG_NAME, NID_organizationName},
+ {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
+ {WOLFSSL_EMAIL_ADDR, NID_emailAddress},
+ {NULL, -1}};
+
+ int i;
+ #ifdef HAVE_ECC
+ int eccEnum;
+ #endif
+ WOLFSSL_ENTER("OBJ_sn2nid");
+ for(i=0; sn2nid[i].sn != NULL; i++) {
+ if(XSTRNCMP(sn, sn2nid[i].sn, XSTRLEN(sn2nid[i].sn)) == 0) {
+ return sn2nid[i].nid;
+ }
+ }
+ #ifdef HAVE_ECC
+ /* Nginx uses this OpenSSL string. */
+ if (XSTRNCMP(sn, "prime256v1", 10) == 0)
+ sn = "SECP256R1";
+ if (XSTRNCMP(sn, "secp384r1", 10) == 0)
+ sn = "SECP384R1";
+ /* find based on name and return NID */
+ for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
+ if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) {
+ eccEnum = ecc_sets[i].id;
+ /* Convert enum value in ecc_curve_id to OpenSSL NID */
+ return EccEnumToNID(eccEnum);
+ }
+ }
+ #endif
+
+ return NID_undef;
+}
+#endif
+
+/* Routine for calculating hashId */
+int CalcHashId(const byte* data, word32 len, byte* hash)
+{
+ int ret;
+
+#ifdef WOLF_CRYPTO_CB
+ /* try to use a registered crypto callback */
+ ret = wc_CryptoCb_Sha256Hash(NULL, data, len, hash);
+ if (ret != CRYPTOCB_UNAVAILABLE)
+ return ret;
+ /* fall-through when unavailable */
+#endif
+
+#if defined(NO_SHA) && !defined(NO_SHA256)
+ ret = wc_Sha256Hash(data, len, hash);
+#elif !defined(NO_SHA)
+ ret = wc_ShaHash(data, len, hash);
+#else
+ ret = NOT_COMPILED_IN;
+#endif
+
+ return ret;
+}
/* process NAME, either issuer or subject */
-static int GetName(DecodedCert* cert, int nameType)
+static int GetName(DecodedCert* cert, int nameType, int maxIdx)
{
int length; /* length of all distinguished names */
int dummy;
int ret;
char* full;
byte* hash;
- word32 idx;
- #ifdef OPENSSL_EXTRA
+ word32 idx, localIdx = 0;
+ byte tag;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
DecodedName* dName =
(nameType == ISSUER) ? &cert->issuerName : &cert->subjectName;
+ int dcnum = 0;
+ #ifdef OPENSSL_EXTRA
+ int count = 0;
+ #endif
#endif /* OPENSSL_EXTRA */
WOLFSSL_MSG("Getting Cert Name");
@@ -1876,13 +5533,20 @@ static int GetName(DecodedCert* cert, int nameType)
hash = cert->subjectHash;
}
- if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) {
+ if (cert->srcIdx >= (word32)maxIdx) {
+ return BUFFER_E;
+ }
+
+ localIdx = cert->srcIdx;
+ if (GetASNTag(cert->source, &localIdx, &tag, maxIdx) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag == ASN_OBJECT_ID) {
WOLFSSL_MSG("Trying optional prefix...");
- if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (SkipObjectId(cert->source, &cert->srcIdx, maxIdx) < 0)
return ASN_PARSE_E;
-
- cert->srcIdx += length;
WOLFSSL_MSG("Got optional prefix");
}
@@ -1890,21 +5554,17 @@ static int GetName(DecodedCert* cert, int nameType)
* calculated over the entire DER encoding of the Name field, including
* the tag and length. */
idx = cert->srcIdx;
- if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0)
return ASN_PARSE_E;
-#ifdef NO_SHA
- ret = wc_Sha256Hash(&cert->source[idx], length + cert->srcIdx - idx, hash);
-#else
- ret = wc_ShaHash(&cert->source[idx], length + cert->srcIdx - idx, hash);
-#endif
+ ret = CalcHashId(&cert->source[idx], length + cert->srcIdx - idx, hash);
if (ret != 0)
return ret;
length += cert->srcIdx;
idx = 0;
-#ifdef HAVE_PKCS7
+#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT)
/* store pointer to raw issuer */
if (nameType == ISSUER) {
cert->issuerRaw = &cert->source[cert->srcIdx];
@@ -1919,45 +5579,39 @@ static int GetName(DecodedCert* cert, int nameType)
#endif
while (cert->srcIdx < (word32)length) {
- byte b;
- byte joint[2];
- byte tooBig = FALSE;
- int oidSz;
-
- if (GetSet(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) {
+ byte b = 0;
+ byte joint[3];
+ byte tooBig = FALSE;
+ int oidSz;
+ const char* copy = NULL;
+ int copyLen = 0;
+ int strLen = 0;
+ byte id = 0;
+
+ if (GetSet(cert->source, &cert->srcIdx, &dummy, maxIdx) < 0) {
WOLFSSL_MSG("Cert name lacks set header, trying sequence");
}
- if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &dummy, maxIdx) <= 0)
return ASN_PARSE_E;
- b = cert->source[cert->srcIdx++];
- if (b != ASN_OBJECT_ID)
- return ASN_OBJECT_ID_E;
+ ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, maxIdx);
+ if (ret != 0)
+ return ret;
- if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0)
+ /* make sure there is room for joint */
+ if ((cert->srcIdx + sizeof(joint)) > (word32)maxIdx)
return ASN_PARSE_E;
XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
/* v1 name types */
if (joint[0] == 0x55 && joint[1] == 0x04) {
- byte id;
- byte copy = FALSE;
- int strLen;
-
- cert->srcIdx += 2;
- id = cert->source[cert->srcIdx++];
- b = cert->source[cert->srcIdx++]; /* encoding */
-
- if (GetLength(cert->source, &cert->srcIdx, &strLen,
- cert->maxIdx) < 0)
+ cert->srcIdx += 3;
+ id = joint[2];
+ if (GetHeader(cert->source, &b, &cert->srcIdx, &strLen,
+ maxIdx, 1) < 0) {
return ASN_PARSE_E;
-
- if ( (strLen + 14) > (int)(ASN_NAME_MAX - idx)) {
- /* include biggest pre fix header too 4 = "/serialNumber=" */
- WOLFSSL_MSG("ASN Name too big, skipping");
- tooBig = TRUE;
}
if (id == ASN_COMMON_NAME) {
@@ -1967,22 +5621,16 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectCNEnc = b;
}
- if (!tooBig) {
- XMEMCPY(&full[idx], "/CN=", 4);
- idx += 4;
- copy = TRUE;
- }
- #ifdef OPENSSL_EXTRA
+ copy = WOLFSSL_COMMON_NAME;
+ copyLen = sizeof(WOLFSSL_COMMON_NAME) - 1;
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->cnIdx = cert->srcIdx;
dName->cnLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_SUR_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/SN=", 4);
- idx += 4;
- copy = TRUE;
- }
+ copy = WOLFSSL_SUR_NAME;
+ copyLen = sizeof(WOLFSSL_SUR_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectSN = (char*)&cert->source[cert->srcIdx];
@@ -1990,17 +5638,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectSNEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->snIdx = cert->srcIdx;
dName->snLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_COUNTRY_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/C=", 3);
- idx += 3;
- copy = TRUE;
- }
+ copy = WOLFSSL_COUNTRY_NAME;
+ copyLen = sizeof(WOLFSSL_COUNTRY_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectC = (char*)&cert->source[cert->srcIdx];
@@ -2008,17 +5653,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectCEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->cIdx = cert->srcIdx;
dName->cLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_LOCALITY_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/L=", 3);
- idx += 3;
- copy = TRUE;
- }
+ copy = WOLFSSL_LOCALITY_NAME;
+ copyLen = sizeof(WOLFSSL_LOCALITY_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectL = (char*)&cert->source[cert->srcIdx];
@@ -2026,17 +5668,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectLEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->lIdx = cert->srcIdx;
dName->lLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_STATE_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/ST=", 4);
- idx += 4;
- copy = TRUE;
- }
+ copy = WOLFSSL_STATE_NAME;
+ copyLen = sizeof(WOLFSSL_STATE_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectST = (char*)&cert->source[cert->srcIdx];
@@ -2044,17 +5683,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectSTEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->stIdx = cert->srcIdx;
dName->stLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_ORG_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/O=", 3);
- idx += 3;
- copy = TRUE;
- }
+ copy = WOLFSSL_ORG_NAME;
+ copyLen = sizeof(WOLFSSL_ORG_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectO = (char*)&cert->source[cert->srcIdx];
@@ -2062,17 +5698,14 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectOEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->oIdx = cert->srcIdx;
dName->oLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_ORGUNIT_NAME) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/OU=", 4);
- idx += 4;
- copy = TRUE;
- }
+ copy = WOLFSSL_ORGUNIT_NAME;
+ copyLen = sizeof(WOLFSSL_ORGUNIT_NAME) - 1;
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectOU = (char*)&cert->source[cert->srcIdx];
@@ -2080,75 +5713,148 @@ static int GetName(DecodedCert* cert, int nameType)
cert->subjectOUEnc = b;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->ouIdx = cert->srcIdx;
dName->ouLen = strLen;
#endif /* OPENSSL_EXTRA */
}
else if (id == ASN_SERIAL_NUMBER) {
- if (!tooBig) {
- XMEMCPY(&full[idx], "/serialNumber=", 14);
- idx += 14;
- copy = TRUE;
- }
- #ifdef OPENSSL_EXTRA
+ copy = WOLFSSL_SERIAL_NUMBER;
+ copyLen = sizeof(WOLFSSL_SERIAL_NUMBER) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectSND = (char*)&cert->source[cert->srcIdx];
+ cert->subjectSNDLen = strLen;
+ cert->subjectSNDEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->snIdx = cert->srcIdx;
dName->snLen = strLen;
#endif /* OPENSSL_EXTRA */
}
+ #ifdef WOLFSSL_CERT_EXT
+ else if (id == ASN_BUS_CAT) {
+ copy = WOLFSSL_BUS_CAT;
+ copyLen = sizeof(WOLFSSL_BUS_CAT) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectBC = (char*)&cert->source[cert->srcIdx];
+ cert->subjectBCLen = strLen;
+ cert->subjectBCEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->bcIdx = cert->srcIdx;
+ dName->bcLen = strLen;
+ #endif /* OPENSSL_EXTRA */
+ }
+ #endif /* WOLFSSL_CERT_EXT */
+ }
+ #ifdef WOLFSSL_CERT_EXT
+ else if ((cert->srcIdx + ASN_JOI_PREFIX_SZ + 2 <= (word32)maxIdx) &&
+ (0 == XMEMCMP(&cert->source[cert->srcIdx], ASN_JOI_PREFIX,
+ ASN_JOI_PREFIX_SZ)) &&
+ ((cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_C) ||
+ (cert->source[cert->srcIdx+ASN_JOI_PREFIX_SZ] == ASN_JOI_ST)))
+ {
+ cert->srcIdx += ASN_JOI_PREFIX_SZ;
+ id = cert->source[cert->srcIdx++];
+ b = cert->source[cert->srcIdx++]; /* encoding */
- if (copy && !tooBig) {
- XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
- idx += strLen;
+ if (GetLength(cert->source, &cert->srcIdx, &strLen,
+ maxIdx) < 0)
+ return ASN_PARSE_E;
+
+ /* Check for jurisdiction of incorporation country name */
+ if (id == ASN_JOI_C) {
+ copy = WOLFSSL_JOI_C;
+ copyLen = sizeof(WOLFSSL_JOI_C) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectJC = (char*)&cert->source[cert->srcIdx];
+ cert->subjectJCLen = strLen;
+ cert->subjectJCEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->jcIdx = cert->srcIdx;
+ dName->jcLen = strLen;
+ #endif /* OPENSSL_EXTRA */
+ }
+
+ /* Check for jurisdiction of incorporation state name */
+ else if (id == ASN_JOI_ST) {
+ copy = WOLFSSL_JOI_ST;
+ copyLen = sizeof(WOLFSSL_JOI_ST) - 1;
+ #ifdef WOLFSSL_CERT_GEN
+ if (nameType == SUBJECT) {
+ cert->subjectJS = (char*)&cert->source[cert->srcIdx];
+ cert->subjectJSLen = strLen;
+ cert->subjectJSEnc = b;
+ }
+ #endif /* WOLFSSL_CERT_GEN */
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->jsIdx = cert->srcIdx;
+ dName->jsLen = strLen;
+ #endif /* OPENSSL_EXTRA */
}
- cert->srcIdx += strLen;
+ if ((strLen + copyLen) > (int)(ASN_NAME_MAX - idx)) {
+ WOLFSSL_MSG("ASN Name too big, skipping");
+ tooBig = TRUE;
+ }
}
+ #endif /* WOLFSSL_CERT_EXT */
else {
/* skip */
byte email = FALSE;
- byte uid = FALSE;
- int adv;
+ byte pilot = FALSE;
- if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */
+ if (joint[0] == 0x2a && joint[1] == 0x86) { /* email id hdr */
+ id = ASN_EMAIL_NAME;
email = TRUE;
+ }
- if (joint[0] == 0x9 && joint[1] == 0x92) /* uid id hdr */
- uid = TRUE;
+ if (joint[0] == 0x9 && joint[1] == 0x92) { /* uid id hdr */
+ /* last value of OID is the type of pilot attribute */
+ id = cert->source[cert->srcIdx + oidSz - 1];
+ pilot = TRUE;
+ }
cert->srcIdx += oidSz + 1;
- if (GetLength(cert->source, &cert->srcIdx, &adv, cert->maxIdx) < 0)
+ if (GetLength(cert->source, &cert->srcIdx, &strLen, maxIdx) < 0)
return ASN_PARSE_E;
- if (adv > (int)(ASN_NAME_MAX - idx)) {
+ if (strLen > (int)(ASN_NAME_MAX - idx)) {
WOLFSSL_MSG("ASN name too big, skipping");
tooBig = TRUE;
}
if (email) {
- if ( (14 + adv) > (int)(ASN_NAME_MAX - idx)) {
+ copyLen = sizeof(WOLFSSL_EMAIL_ADDR) - 1;
+ if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx)) {
WOLFSSL_MSG("ASN name too big, skipping");
tooBig = TRUE;
}
- if (!tooBig) {
- XMEMCPY(&full[idx], "/emailAddress=", 14);
- idx += 14;
+ else {
+ copy = WOLFSSL_EMAIL_ADDR;
}
#ifdef WOLFSSL_CERT_GEN
if (nameType == SUBJECT) {
cert->subjectEmail = (char*)&cert->source[cert->srcIdx];
- cert->subjectEmailLen = adv;
+ cert->subjectEmailLen = strLen;
}
#endif /* WOLFSSL_CERT_GEN */
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
dName->emailIdx = cert->srcIdx;
- dName->emailLen = adv;
+ dName->emailLen = strLen;
#endif /* OPENSSL_EXTRA */
#ifndef IGNORE_NAME_CONSTRAINTS
{
- DNS_entry* emailName = NULL;
+ DNS_entry* emailName;
emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry),
cert->heap, DYNAMIC_TYPE_ALTNAME);
@@ -2156,52 +5862,85 @@ static int GetName(DecodedCert* cert, int nameType)
WOLFSSL_MSG("\tOut of Memory");
return MEMORY_E;
}
- emailName->name = (char*)XMALLOC(adv + 1,
+ emailName->type = 0;
+ emailName->name = (char*)XMALLOC(strLen + 1,
cert->heap, DYNAMIC_TYPE_ALTNAME);
if (emailName->name == NULL) {
WOLFSSL_MSG("\tOut of Memory");
+ XFREE(emailName, cert->heap, DYNAMIC_TYPE_ALTNAME);
return MEMORY_E;
}
- XMEMCPY(emailName->name,
- &cert->source[cert->srcIdx], adv);
- emailName->name[adv] = 0;
+ emailName->len = strLen;
+ XMEMCPY(emailName->name, &cert->source[cert->srcIdx],
+ strLen);
+ emailName->name[strLen] = '\0';
emailName->next = cert->altEmailNames;
cert->altEmailNames = emailName;
}
#endif /* IGNORE_NAME_CONSTRAINTS */
- if (!tooBig) {
- XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
- idx += adv;
- }
}
- if (uid) {
- if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) {
- WOLFSSL_MSG("ASN name too big, skipping");
- tooBig = TRUE;
- }
- if (!tooBig) {
- XMEMCPY(&full[idx], "/UID=", 5);
- idx += 5;
+ if (pilot) {
+ switch (id) {
+ case ASN_USER_ID:
+ copy = WOLFSSL_USER_ID;
+ copyLen = sizeof(WOLFSSL_USER_ID) - 1;
+ #if defined(OPENSSL_EXTRA) || \
+ defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->uidIdx = cert->srcIdx;
+ dName->uidLen = strLen;
+ #endif /* OPENSSL_EXTRA */
+ break;
- XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv);
- idx += adv;
+ case ASN_DOMAIN_COMPONENT:
+ copy = WOLFSSL_DOMAIN_COMPONENT;
+ copyLen = sizeof(WOLFSSL_DOMAIN_COMPONENT) - 1;
+ #if defined(OPENSSL_EXTRA) || \
+ defined(OPENSSL_EXTRA_X509_SMALL)
+ dName->dcIdx[dcnum] = cert->srcIdx;
+ dName->dcLen[dcnum] = strLen;
+ dName->dcNum = dcnum + 1;
+ dcnum++;
+ #endif /* OPENSSL_EXTRA */
+ break;
+
+ default:
+ WOLFSSL_MSG("Unknown pilot attribute type");
+ return ASN_PARSE_E;
}
- #ifdef OPENSSL_EXTRA
- dName->uidIdx = cert->srcIdx;
- dName->uidLen = adv;
- #endif /* OPENSSL_EXTRA */
}
+ }
+ if ((copyLen + strLen) > (int)(ASN_NAME_MAX - idx))
+ {
+ WOLFSSL_MSG("ASN Name too big, skipping");
+ tooBig = TRUE;
+ }
+ if ((copy != NULL) && !tooBig) {
+ XMEMCPY(&full[idx], copy, copyLen);
+ idx += copyLen;
+ XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
+ idx += strLen;
- cert->srcIdx += adv;
+ #ifdef OPENSSL_EXTRA
+ if (count < DOMAIN_COMPONENT_MAX) {
+ /* store order that DN was parsed */
+ dName->loc[count++] = id;
+ }
+ #endif
}
+ cert->srcIdx += strLen;
}
full[idx++] = 0;
+#if defined(OPENSSL_EXTRA)
+ /* store order that DN was parsed */
+ dName->locSz = count;
+#endif
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
{
int totalLen = 0;
+ int i = 0;
if (dName->cnLen != 0)
totalLen += dName->cnLen + 4;
@@ -2223,14 +5962,20 @@ static int GetName(DecodedCert* cert, int nameType)
totalLen += dName->uidLen + 5;
if (dName->serialLen != 0)
totalLen += dName->serialLen + 14;
+ if (dName->dcNum != 0){
+ for (i = 0;i < dName->dcNum;i++)
+ totalLen += dName->dcLen[i] + 4;
+ }
- dName->fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509);
+ dName->fullName = (char*)XMALLOC(totalLen + 1, cert->heap,
+ DYNAMIC_TYPE_X509);
if (dName->fullName != NULL) {
idx = 0;
if (dName->cnLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/CN=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_COMMON_NAME, 4);
+ dName->cnNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COMMON_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->cnIdx], dName->cnLen);
@@ -2239,7 +5984,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->snLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/SN=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_SUR_NAME, 4);
+ dName->snNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SUR_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->snIdx], dName->snLen);
@@ -2248,7 +5994,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->cLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/C=", 3);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_COUNTRY_NAME, 3);
+ dName->cNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COUNTRY_NAME);
idx += 3;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->cIdx], dName->cLen);
@@ -2257,7 +6004,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->lLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/L=", 3);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_LOCALITY_NAME, 3);
+ dName->lNid = wc_OBJ_sn2nid((const char *)WOLFSSL_LOCALITY_NAME);
idx += 3;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->lIdx], dName->lLen);
@@ -2266,7 +6014,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->stLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/ST=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_STATE_NAME, 4);
+ dName->stNid = wc_OBJ_sn2nid((const char *)WOLFSSL_STATE_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->stIdx], dName->stLen);
@@ -2275,7 +6024,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->oLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/O=", 3);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_ORG_NAME, 3);
+ dName->oNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORG_NAME);
idx += 3;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->oIdx], dName->oLen);
@@ -2284,7 +6034,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->ouLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/OU=", 4);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_ORGUNIT_NAME, 4);
+ dName->ouNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORGUNIT_NAME);
idx += 4;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->ouIdx], dName->ouLen);
@@ -2294,15 +6045,28 @@ static int GetName(DecodedCert* cert, int nameType)
if (dName->emailLen != 0) {
dName->entryCount++;
XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14);
+ dName->emailNid = wc_OBJ_sn2nid((const char *)"/emailAddress=");
idx += 14;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->emailIdx], dName->emailLen);
dName->emailIdx = idx;
idx += dName->emailLen;
}
+ for (i = 0;i < dName->dcNum;i++){
+ if (dName->dcLen[i] != 0) {
+ dName->entryCount++;
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_DOMAIN_COMPONENT, 4);
+ idx += 4;
+ XMEMCPY(&dName->fullName[idx],
+ &cert->source[dName->dcIdx[i]], dName->dcLen[i]);
+ dName->dcIdx[i] = idx;
+ idx += dName->dcLen[i];
+ }
+ }
if (dName->uidLen != 0) {
dName->entryCount++;
XMEMCPY(&dName->fullName[idx], "/UID=", 5);
+ dName->uidNid = wc_OBJ_sn2nid((const char *)"/UID=");
idx += 5;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->uidIdx], dName->uidLen);
@@ -2311,7 +6075,8 @@ static int GetName(DecodedCert* cert, int nameType)
}
if (dName->serialLen != 0) {
dName->entryCount++;
- XMEMCPY(&dName->fullName[idx], "/serialNumber=", 14);
+ XMEMCPY(&dName->fullName[idx], WOLFSSL_SERIAL_NUMBER, 14);
+ dName->serialNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SERIAL_NUMBER);
idx += 14;
XMEMCPY(&dName->fullName[idx],
&cert->source[dName->serialIdx], dName->serialLen);
@@ -2328,17 +6093,203 @@ static int GetName(DecodedCert* cert, int nameType)
}
-#ifndef NO_TIME_H
+#ifndef NO_ASN_TIME
+
+/* two byte date/time, add to value */
+static WC_INLINE int GetTime(int* value, const byte* date, int* idx)
+{
+ int i = *idx;
+
+ if (date[i] < 0x30 || date[i] > 0x39 || date[i+1] < 0x30 ||
+ date[i+1] > 0x39) {
+ return ASN_PARSE_E;
+ }
+
+ *value += btoi(date[i++]) * 10;
+ *value += btoi(date[i++]);
+
+ *idx = i;
+
+ return 0;
+}
+
+int ExtractDate(const unsigned char* date, unsigned char format,
+ struct tm* certTime, int* idx)
+{
+ XMEMSET(certTime, 0, sizeof(struct tm));
+
+ if (format == ASN_UTC_TIME) {
+ if (btoi(date[*idx]) >= 5)
+ certTime->tm_year = 1900;
+ else
+ certTime->tm_year = 2000;
+ }
+ else { /* format == GENERALIZED_TIME */
+ if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+ certTime->tm_year *= 100;
+ }
+
+ /* adjust tm_year, tm_mon */
+ if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+ certTime->tm_year -= 1900;
+ if (GetTime(&certTime->tm_mon , date, idx) != 0) return 0;
+ certTime->tm_mon -= 1;
+ if (GetTime(&certTime->tm_mday, date, idx) != 0) return 0;
+ if (GetTime(&certTime->tm_hour, date, idx) != 0) return 0;
+ if (GetTime(&certTime->tm_min , date, idx) != 0) return 0;
+ if (GetTime(&certTime->tm_sec , date, idx) != 0) return 0;
+
+ return 1;
+}
+
+
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
+ defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+int GetTimeString(byte* date, int format, char* buf, int len)
+{
+ struct tm t;
+ int idx = 0;
+
+ if (!ExtractDate(date, (unsigned char)format, &t, &idx)) {
+ return 0;
+ }
+
+ if (date[idx] != 'Z') {
+ WOLFSSL_MSG("UTCtime, not Zulu") ;
+ return 0;
+ }
+
+ /* place month in buffer */
+ buf[0] = '\0';
+ switch(t.tm_mon) {
+ case 0: XSTRNCAT(buf, "Jan ", 5); break;
+ case 1: XSTRNCAT(buf, "Feb ", 5); break;
+ case 2: XSTRNCAT(buf, "Mar ", 5); break;
+ case 3: XSTRNCAT(buf, "Apr ", 5); break;
+ case 4: XSTRNCAT(buf, "May ", 5); break;
+ case 5: XSTRNCAT(buf, "Jun ", 5); break;
+ case 6: XSTRNCAT(buf, "Jul ", 5); break;
+ case 7: XSTRNCAT(buf, "Aug ", 5); break;
+ case 8: XSTRNCAT(buf, "Sep ", 5); break;
+ case 9: XSTRNCAT(buf, "Oct ", 5); break;
+ case 10: XSTRNCAT(buf, "Nov ", 5); break;
+ case 11: XSTRNCAT(buf, "Dec ", 5); break;
+ default:
+ return 0;
+
+ }
+ idx = 4; /* use idx now for char buffer */
+
+ XSNPRINTF(buf + idx, len - idx, "%2d %02d:%02d:%02d %d GMT",
+ t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, t.tm_year + 1900);
+
+ return 1;
+}
+#endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
+
+
+#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7)
+
+/* Set current time string, either UTC or GeneralizedTime.
+ * (void*) tm should be a pointer to time_t, output is placed in buf.
+ *
+ * Return time string length placed in buf on success, negative on error */
+int GetAsnTimeString(void* currTime, byte* buf, word32 len)
+{
+ struct tm* ts = NULL;
+ struct tm* tmpTime = NULL;
+#if defined(NEED_TMP_TIME)
+ struct tm tmpTimeStorage;
+ tmpTime = &tmpTimeStorage;
+#else
+ (void)tmpTime;
+#endif
+ byte* data_ptr = buf;
+ word32 data_len = 0;
+ int year, mon, day, hour, mini, sec;
+
+ WOLFSSL_ENTER("SetAsnTimeString");
+
+ if (buf == NULL || len == 0)
+ return BAD_FUNC_ARG;
+
+ ts = (struct tm *)XGMTIME((time_t*)currTime, tmpTime);
+ if (ts == NULL){
+ WOLFSSL_MSG("failed to get time data.");
+ return ASN_TIME_E;
+ }
+
+ /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for
+ * the null terminator. ASN encoded values leave off the terminator. */
+
+ if (ts->tm_year >= 50 && ts->tm_year < 150) {
+ /* UTC Time */
+ char utc_str[ASN_UTC_TIME_SIZE];
+ data_len = ASN_UTC_TIME_SIZE - 1 + 2;
+
+ if (len < data_len)
+ return BUFFER_E;
+
+ if (ts->tm_year >= 50 && ts->tm_year < 100) {
+ year = ts->tm_year;
+ } else if (ts->tm_year >= 100 && ts->tm_year < 150) {
+ year = ts->tm_year - 100;
+ }
+ else {
+ WOLFSSL_MSG("unsupported year range");
+ return BAD_FUNC_ARG;
+ }
+ mon = ts->tm_mon + 1;
+ day = ts->tm_mday;
+ hour = ts->tm_hour;
+ mini = ts->tm_min;
+ sec = ts->tm_sec;
+ XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE,
+ "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
+ *data_ptr = (byte) ASN_UTC_TIME; data_ptr++;
+ /* -1 below excludes null terminator */
+ *data_ptr = (byte) ASN_UTC_TIME_SIZE - 1; data_ptr++;
+ XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE - 1);
+
+ } else {
+ /* GeneralizedTime */
+ char gt_str[ASN_GENERALIZED_TIME_SIZE];
+ data_len = ASN_GENERALIZED_TIME_SIZE - 1 + 2;
+
+ if (len < data_len)
+ return BUFFER_E;
+
+ year = ts->tm_year + 1900;
+ mon = ts->tm_mon + 1;
+ day = ts->tm_mday;
+ hour = ts->tm_hour;
+ mini = ts->tm_min;
+ sec = ts->tm_sec;
+ XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE,
+ "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec);
+ *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++;
+ /* -1 below excludes null terminator */
+ *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE - 1; data_ptr++;
+ XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE - 1);
+ }
+
+ return data_len;
+}
+
+#endif /* !NO_ASN_TIME && HAVE_PKCS7 */
+
+
+#if defined(USE_WOLF_VALIDDATE)
/* to the second */
-static int DateGreaterThan(const struct tm* a, const struct tm* b)
+int DateGreaterThan(const struct tm* a, const struct tm* b)
{
if (a->tm_year > b->tm_year)
return 1;
if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon)
return 1;
-
+
if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon &&
a->tm_mday > b->tm_mday)
return 1;
@@ -2361,12 +6312,11 @@ static int DateGreaterThan(const struct tm* a, const struct tm* b)
}
-static INLINE int DateLessThan(const struct tm* a, const struct tm* b)
+static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b)
{
return DateGreaterThan(b,a);
}
-
/* like atoi but only use first byte */
/* Make sure before and after dates are valid */
int ValidateDate(const byte* date, byte format, int dateType)
@@ -2374,64 +6324,142 @@ int ValidateDate(const byte* date, byte format, int dateType)
time_t ltime;
struct tm certTime;
struct tm* localTime;
- struct tm* tmpTime = NULL;
+ struct tm* tmpTime;
int i = 0;
+ int timeDiff = 0 ;
+ int diffHH = 0 ; int diffMM = 0 ;
+ int diffSign = 0 ;
-#if defined(FREESCALE_MQX) || defined(TIME_OVERRIDES)
+#if defined(NEED_TMP_TIME)
struct tm tmpTimeStorage;
tmpTime = &tmpTimeStorage;
#else
- (void)tmpTime;
+ tmpTime = NULL;
#endif
+ (void)tmpTime;
ltime = XTIME(0);
- XMEMSET(&certTime, 0, sizeof(certTime));
- if (format == ASN_UTC_TIME) {
- if (btoi(date[0]) >= 5)
- certTime.tm_year = 1900;
- else
- certTime.tm_year = 2000;
+#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW
+ if (dateType == BEFORE) {
+ WOLFSSL_MSG("Skewing local time for before date check");
+ ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW;
}
- else { /* format == GENERALIZED_TIME */
- certTime.tm_year += btoi(date[i++]) * 1000;
- certTime.tm_year += btoi(date[i++]) * 100;
+#endif
+
+#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW
+ if (dateType == AFTER) {
+ WOLFSSL_MSG("Skewing local time for after date check");
+ ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW;
}
+#endif
- /* adjust tm_year, tm_mon */
- GetTime((int*)&certTime.tm_year, date, &i); certTime.tm_year -= 1900;
- GetTime((int*)&certTime.tm_mon, date, &i); certTime.tm_mon -= 1;
- GetTime((int*)&certTime.tm_mday, date, &i);
- GetTime((int*)&certTime.tm_hour, date, &i);
- GetTime((int*)&certTime.tm_min, date, &i);
- GetTime((int*)&certTime.tm_sec, date, &i);
-
- if (date[i] != 'Z') { /* only Zulu supported for this profile */
- WOLFSSL_MSG("Only Zulu time supported for this profile");
+ if (!ExtractDate(date, format, &certTime, &i)) {
+ WOLFSSL_MSG("Error extracting the date");
return 0;
}
+ if ((date[i] == '+') || (date[i] == '-')) {
+ WOLFSSL_MSG("Using time differential, not Zulu") ;
+ diffSign = date[i++] == '+' ? 1 : -1 ;
+ if (GetTime(&diffHH, date, &i) != 0)
+ return 0;
+ if (GetTime(&diffMM, date, &i) != 0)
+ return 0;
+ timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ;
+ } else if (date[i] != 'Z') {
+ WOLFSSL_MSG("UTCtime, neither Zulu or time differential") ;
+ return 0;
+ }
+
+ ltime -= (time_t)timeDiff ;
localTime = XGMTIME(&ltime, tmpTime);
+ if (localTime == NULL) {
+ WOLFSSL_MSG("XGMTIME failed");
+ return 0;
+ }
+
if (dateType == BEFORE) {
- if (DateLessThan(localTime, &certTime))
+ if (DateLessThan(localTime, &certTime)) {
+ WOLFSSL_MSG("Date BEFORE check failed");
return 0;
+ }
}
- else
- if (DateGreaterThan(localTime, &certTime))
+ else { /* dateType == AFTER */
+ if (DateGreaterThan(localTime, &certTime)) {
+ WOLFSSL_MSG("Date AFTER check failed");
return 0;
+ }
+ }
return 1;
}
+#endif /* USE_WOLF_VALIDDATE */
+
+int wc_GetTime(void* timePtr, word32 timeSize)
+{
+ time_t* ltime = (time_t*)timePtr;
+
+ if (timePtr == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if ((word32)sizeof(time_t) > timeSize) {
+ return BUFFER_E;
+ }
+
+ *ltime = XTIME(0);
+
+ return 0;
+}
-#endif /* NO_TIME_H */
+#endif /* !NO_ASN_TIME */
-static int GetDate(DecodedCert* cert, int dateType)
+/* Get date buffer, format and length. Returns 0=success or error */
+static int GetDateInfo(const byte* source, word32* idx, const byte** pDate,
+ byte* pFormat, int* pLength, word32 maxIdx)
{
- int length;
+ int length;
+ byte format;
+
+ if (source == NULL || idx == NULL)
+ return BAD_FUNC_ARG;
+
+ /* get ASN format header */
+ if (*idx+1 > maxIdx)
+ return BUFFER_E;
+ format = source[*idx];
+ *idx += 1;
+ if (format != ASN_UTC_TIME && format != ASN_GENERALIZED_TIME)
+ return ASN_TIME_E;
+
+ /* get length */
+ if (GetLength(source, idx, &length, maxIdx) < 0)
+ return ASN_PARSE_E;
+ if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
+ return ASN_DATE_SZ_E;
+
+ /* return format, date and length */
+ if (pFormat)
+ *pFormat = format;
+ if (pDate)
+ *pDate = &source[*idx];
+ if (pLength)
+ *pLength = length;
+
+ *idx += length;
+
+ return 0;
+}
+
+static int GetDate(DecodedCert* cert, int dateType, int verify, int maxIdx)
+{
+ int ret, length;
+ const byte *datePtr = NULL;
byte date[MAX_DATE_SIZE];
- byte b;
+ byte format;
word32 startIdx = 0;
if (dateType == BEFORE)
@@ -2440,49 +6468,50 @@ static int GetDate(DecodedCert* cert, int dateType)
cert->afterDate = &cert->source[cert->srcIdx];
startIdx = cert->srcIdx;
- b = cert->source[cert->srcIdx++];
- if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME)
- return ASN_TIME_E;
-
- if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
- return ASN_PARSE_E;
-
- if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
- return ASN_DATE_SZ_E;
+ ret = GetDateInfo(cert->source, &cert->srcIdx, &datePtr, &format,
+ &length, maxIdx);
+ if (ret < 0)
+ return ret;
- XMEMCPY(date, &cert->source[cert->srcIdx], length);
- cert->srcIdx += length;
+ XMEMSET(date, 0, MAX_DATE_SIZE);
+ XMEMCPY(date, datePtr, length);
if (dateType == BEFORE)
cert->beforeDateLen = cert->srcIdx - startIdx;
else
cert->afterDateLen = cert->srcIdx - startIdx;
- if (!XVALIDATE_DATE(date, b, dateType)) {
+#ifndef NO_ASN_TIME
+ if (verify != NO_VERIFY && verify != VERIFY_SKIP_DATE &&
+ !XVALIDATE_DATE(date, format, dateType)) {
if (dateType == BEFORE)
return ASN_BEFORE_DATE_E;
else
return ASN_AFTER_DATE_E;
}
+#else
+ (void)verify;
+#endif
return 0;
}
-
-static int GetValidity(DecodedCert* cert, int verify)
+static int GetValidity(DecodedCert* cert, int verify, int maxIdx)
{
int length;
int badDate = 0;
- if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
+ if (GetSequence(cert->source, &cert->srcIdx, &length, maxIdx) < 0)
return ASN_PARSE_E;
- if (GetDate(cert, BEFORE) < 0 && verify)
- badDate = ASN_BEFORE_DATE_E; /* continue parsing */
-
- if (GetDate(cert, AFTER) < 0 && verify)
+ maxIdx = cert->srcIdx + length;
+
+ if (GetDate(cert, BEFORE, verify, maxIdx) < 0)
+ badDate = ASN_BEFORE_DATE_E; /* continue parsing */
+
+ if (GetDate(cert, AFTER, verify, maxIdx) < 0)
return ASN_AFTER_DATE_E;
-
+
if (badDate != 0)
return badDate;
@@ -2490,32 +6519,111 @@ static int GetValidity(DecodedCert* cert, int verify)
}
-int DecodeToKey(DecodedCert* cert, int verify)
+int wc_GetDateInfo(const byte* certDate, int certDateSz, const byte** date,
+ byte* format, int* length)
{
- int badDate = 0;
int ret;
+ word32 idx = 0;
+
+ ret = GetDateInfo(certDate, &idx, date, format, length, certDateSz);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+#ifndef NO_ASN_TIME
+int wc_GetDateAsCalendarTime(const byte* date, int length, byte format,
+ struct tm* timearg)
+{
+ int idx = 0;
+ (void)length;
+ if (!ExtractDate(date, format, timearg, &idx))
+ return ASN_TIME_E;
+ return 0;
+}
+
+#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_ALT_NAMES)
+int wc_GetCertDates(Cert* cert, struct tm* before, struct tm* after)
+{
+ int ret = 0;
+ const byte* date;
+ byte format;
+ int length;
+ if (cert == NULL)
+ return BAD_FUNC_ARG;
+
+ if (before && cert->beforeDateSz > 0) {
+ ret = wc_GetDateInfo(cert->beforeDate, cert->beforeDateSz, &date,
+ &format, &length);
+ if (ret == 0)
+ ret = wc_GetDateAsCalendarTime(date, length, format, before);
+ }
+ if (after && cert->afterDateSz > 0) {
+ ret = wc_GetDateInfo(cert->afterDate, cert->afterDateSz, &date,
+ &format, &length);
+ if (ret == 0)
+ ret = wc_GetDateAsCalendarTime(date, length, format, after);
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_CERT_GEN && WOLFSSL_ALT_NAMES */
+#endif /* !NO_ASN_TIME */
+
+/* parses certificate up to point of X.509 public key
+ *
+ * if cert date is invalid then badDate gets set to error value, otherwise is 0
+ *
+ * returns a negative value on fail case
+ */
+int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate)
+{
+ int ret;
+
+ if (cert == NULL || badDate == NULL)
+ return BAD_FUNC_ARG;
+
+ *badDate = 0;
if ( (ret = GetCertHeader(cert)) < 0)
return ret;
WOLFSSL_MSG("Got Cert Header");
+ /* Using the sigIndex as the upper bound because that's where the
+ * actual certificate data ends. */
if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
- cert->maxIdx)) < 0)
+ oidSigType, cert->sigIndex)) < 0)
return ret;
WOLFSSL_MSG("Got Algo ID");
- if ( (ret = GetName(cert, ISSUER)) < 0)
+ if ( (ret = GetName(cert, ISSUER, cert->sigIndex)) < 0)
return ret;
- if ( (ret = GetValidity(cert, verify)) < 0)
- badDate = ret;
+ if ( (ret = GetValidity(cert, verify, cert->sigIndex)) < 0)
+ *badDate = ret;
- if ( (ret = GetName(cert, SUBJECT)) < 0)
+ if ( (ret = GetName(cert, SUBJECT, cert->sigIndex)) < 0)
return ret;
WOLFSSL_MSG("Got Subject Name");
+ return ret;
+}
+
+int DecodeToKey(DecodedCert* cert, int verify)
+{
+ int badDate = 0;
+ int ret;
+
+ if ( (ret = wc_GetPubX509(cert, verify, &badDate)) < 0)
+ return ret;
+
+ /* Determine if self signed */
+ cert->selfSigned = XMEMCMP(cert->issuerHash,
+ cert->subjectHash,
+ KEYID_SIZE) == 0 ? 1 : 0;
if ( (ret = GetKey(cert)) < 0)
return ret;
@@ -2528,40 +6636,36 @@ int DecodeToKey(DecodedCert* cert, int verify)
return ret;
}
-
static int GetSignature(DecodedCert* cert)
{
- int length;
- byte b = cert->source[cert->srcIdx++];
-
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
-
- if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
- return ASN_PARSE_E;
+ int length;
+ int ret;
+ ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1,
+ NULL);
+ if (ret != 0)
+ return ret;
cert->sigLength = length;
-
- b = cert->source[cert->srcIdx++];
- if (b != 0x00)
- return ASN_EXPECT_0_E;
-
- cert->sigLength--;
cert->signature = &cert->source[cert->srcIdx];
cert->srcIdx += cert->sigLength;
return 0;
}
+static word32 SetOctetString8Bit(word32 len, byte* output)
+{
+ output[0] = ASN_OCTET_STRING;
+ output[1] = (byte)len;
+ return 2;
+}
static word32 SetDigest(const byte* digest, word32 digSz, byte* output)
{
- output[0] = ASN_OCTET_STRING;
- output[1] = (byte)digSz;
- XMEMCPY(&output[2], digest, digSz);
+ word32 idx = SetOctetString8Bit(digSz, output);
+ XMEMCPY(&output[idx], digest, digSz);
- return digSz + 2;
-}
+ return idx + digSz;
+}
static word32 BytePrecision(word32 value)
@@ -2575,17 +6679,23 @@ static word32 BytePrecision(word32 value)
}
-WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output)
+word32 SetLength(word32 length, byte* output)
{
word32 i = 0, j;
- if (length < ASN_LONG_LENGTH)
- output[i++] = (byte)length;
+ if (length < ASN_LONG_LENGTH) {
+ if (output)
+ output[i] = (byte)length;
+ i++;
+ }
else {
- output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
-
+ if (output)
+ output[i] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH);
+ i++;
+
for (j = BytePrecision(length); j; --j) {
- output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE));
+ if (output)
+ output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE));
i++;
}
}
@@ -2593,27 +6703,27 @@ WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output)
return i;
}
-
-WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output)
+word32 SetSequence(word32 len, byte* output)
{
- output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
- return SetLength(len, output + 1) + 1;
+ if (output)
+ output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
+ return SetLength(len, output ? output + 1 : NULL) + 1;
}
-WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output)
+word32 SetOctetString(word32 len, byte* output)
{
output[0] = ASN_OCTET_STRING;
return SetLength(len, output + 1) + 1;
}
/* Write a set header to output */
-WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output)
+word32 SetSet(word32 len, byte* output)
{
output[0] = ASN_SET | ASN_CONSTRUCTED;
return SetLength(len, output + 1) + 1;
}
-WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
+word32 SetImplicit(byte tag, byte number, word32 len, byte* output)
{
output[0] = ((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0)
@@ -2621,323 +6731,121 @@ WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output
return SetLength(len, output + 1) + 1;
}
-WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output)
+word32 SetExplicit(byte number, word32 len, byte* output)
{
output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number;
return SetLength(len, output + 1) + 1;
}
-#if defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
+#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
-static word32 SetCurve(ecc_key* key, byte* output)
+static int SetCurve(ecc_key* key, byte* output)
{
-
- /* curve types */
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- static const byte ECC_192v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x03, 0x01, 0x01};
-#endif
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- static const byte ECC_256v1_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x03, 0x01, 0x07};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- static const byte ECC_160r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x02};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- static const byte ECC_224r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x21};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- static const byte ECC_384r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x22};
-#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- static const byte ECC_521r1_AlgoID[] = { 0x2b, 0x81, 0x04, 0x00,
- 0x23};
-#endif
-
- int oidSz = 0;
- int idx = 0;
- int lenSz = 0;
- const byte* oid = 0;
-
- output[0] = ASN_OBJECT_ID;
- idx++;
-
- switch (key->dp->size) {
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC160)
- case 20:
- oidSz = sizeof(ECC_160r1_AlgoID);
- oid = ECC_160r1_AlgoID;
- break;
-#endif
-
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC192)
- case 24:
- oidSz = sizeof(ECC_192v1_AlgoID);
- oid = ECC_192v1_AlgoID;
- break;
-#endif
-
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC224)
- case 28:
- oidSz = sizeof(ECC_224r1_AlgoID);
- oid = ECC_224r1_AlgoID;
- break;
+#ifdef HAVE_OID_ENCODING
+ int ret;
#endif
+ int idx = 0;
+ word32 oidSz = 0;
-#if defined(HAVE_ALL_CURVES) || !defined(NO_ECC256)
- case 32:
- oidSz = sizeof(ECC_256v1_AlgoID);
- oid = ECC_256v1_AlgoID;
- break;
-#endif
+ /* validate key */
+ if (key == NULL || key->dp == NULL) {
+ return BAD_FUNC_ARG;
+ }
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC384)
- case 48:
- oidSz = sizeof(ECC_384r1_AlgoID);
- oid = ECC_384r1_AlgoID;
- break;
+#ifdef HAVE_OID_ENCODING
+ ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, NULL, &oidSz);
+ if (ret != 0) {
+ return ret;
+ }
+#else
+ oidSz = key->dp->oidSz;
#endif
-#if defined(HAVE_ALL_CURVES) || defined(HAVE_ECC521)
- case 66:
- oidSz = sizeof(ECC_521r1_AlgoID);
- oid = ECC_521r1_AlgoID;
- break;
-#endif
+ idx += SetObjectId(oidSz, output);
- default:
- return ASN_UNKNOWN_OID_E;
+#ifdef HAVE_OID_ENCODING
+ ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz);
+ if (ret != 0) {
+ return ret;
}
- lenSz = SetLength(oidSz, output+idx);
- idx += lenSz;
-
- XMEMCPY(output+idx, oid, oidSz);
+#else
+ XMEMCPY(output+idx, key->dp->oid, oidSz);
+#endif
idx += oidSz;
return idx;
}
-#endif /* HAVE_ECC && WOLFSSL_CERT_GEN */
+#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
-WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
+#ifdef HAVE_ECC
+static WC_INLINE int IsSigAlgoECDSA(int algoOID)
{
- /* adding TAG_NULL and 0 to end */
-
- /* hashTypes */
- static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
- 0x05, 0x00 };
- static const byte sha256AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
- 0x04, 0x02, 0x01, 0x05, 0x00 };
- static const byte sha384AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
- 0x04, 0x02, 0x02, 0x05, 0x00 };
- static const byte sha512AlgoID[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
- 0x04, 0x02, 0x03, 0x05, 0x00 };
- static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x02, 0x05, 0x05, 0x00 };
- static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x02, 0x02, 0x05, 0x00};
-
- /* blkTypes, no NULL tags because IV is there instead */
- static const byte desCbcAlgoID[] = { 0x2B, 0x0E, 0x03, 0x02, 0x07 };
- static const byte des3CbcAlgoID[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x03, 0x07 };
-
- /* RSA sigTypes */
- #ifndef NO_RSA
- static const byte md5wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00};
- static const byte shawRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00};
- static const byte sha256wRSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00};
- static const byte sha384wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00};
- static const byte sha512wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00};
- #endif /* NO_RSA */
-
- /* ECDSA sigTypes */
- #ifdef HAVE_ECC
- static const byte shawECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x04, 0x01, 0x05, 0x00};
- static const byte sha256wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
- 0x04, 0x03, 0x02, 0x05, 0x00};
- static const byte sha384wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
- 0x04, 0x03, 0x03, 0x05, 0x00};
- static const byte sha512wECDSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE,0x3d,
- 0x04, 0x03, 0x04, 0x05, 0x00};
- #endif /* HAVE_ECC */
-
- /* RSA keyType */
- #ifndef NO_RSA
- static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00};
- #endif /* NO_RSA */
+ /* ECDSA sigAlgo must not have ASN1 NULL parameters */
+ if (algoOID == CTC_SHAwECDSA || algoOID == CTC_SHA256wECDSA ||
+ algoOID == CTC_SHA384wECDSA || algoOID == CTC_SHA512wECDSA) {
+ return 1;
+ }
- #ifdef HAVE_ECC
- /* ECC keyType */
- /* no tags, so set tagSz smaller later */
- static const byte ECC_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d,
- 0x02, 0x01};
- #endif /* HAVE_ECC */
+ return 0;
+}
+#endif
- int algoSz = 0;
- int tagSz = 2; /* tag null and terminator */
- word32 idSz, seqSz;
+word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
+{
+ word32 tagSz, idSz, seqSz, algoSz = 0;
const byte* algoName = 0;
- byte ID_Length[MAX_LENGTH_SZ];
- byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
-
- if (type == hashType) {
- switch (algoOID) {
- case SHAh:
- algoSz = sizeof(shaAlgoID);
- algoName = shaAlgoID;
- break;
-
- case SHA256h:
- algoSz = sizeof(sha256AlgoID);
- algoName = sha256AlgoID;
- break;
-
- case SHA384h:
- algoSz = sizeof(sha384AlgoID);
- algoName = sha384AlgoID;
- break;
-
- case SHA512h:
- algoSz = sizeof(sha512AlgoID);
- algoName = sha512AlgoID;
- break;
+ byte ID_Length[1 + MAX_LENGTH_SZ];
+ byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
+ int length = 0;
+
+ tagSz = (type == oidHashType ||
+ (type == oidSigType
+ #ifdef HAVE_ECC
+ && !IsSigAlgoECDSA(algoOID)
+ #endif
+ #ifdef HAVE_ED25519
+ && algoOID != ED25519k
+ #endif
+ #ifdef HAVE_ED448
+ && algoOID != ED448k
+ #endif
+ ) ||
+ (type == oidKeyType && algoOID == RSAk)) ? 2 : 0;
- case MD2h:
- algoSz = sizeof(md2AlgoID);
- algoName = md2AlgoID;
- break;
+ algoName = OidFromId(algoOID, type, &algoSz);
- case MD5h:
- algoSz = sizeof(md5AlgoID);
- algoName = md5AlgoID;
- break;
-
- default:
- WOLFSSL_MSG("Unknown Hash Algo");
- return 0; /* UNKOWN_HASH_E; */
- }
- }
- else if (type == blkType) {
- switch (algoOID) {
- case DESb:
- algoSz = sizeof(desCbcAlgoID);
- algoName = desCbcAlgoID;
- tagSz = 0;
- break;
- case DES3b:
- algoSz = sizeof(des3CbcAlgoID);
- algoName = des3CbcAlgoID;
- tagSz = 0;
- break;
- default:
- WOLFSSL_MSG("Unknown Block Algo");
- return 0;
- }
+ if (algoName == NULL) {
+ WOLFSSL_MSG("Unknown Algorithm");
+ return 0;
}
- else if (type == sigType) { /* sigType */
- switch (algoOID) {
- #ifndef NO_RSA
- case CTC_MD5wRSA:
- algoSz = sizeof(md5wRSA_AlgoID);
- algoName = md5wRSA_AlgoID;
- break;
- case CTC_SHAwRSA:
- algoSz = sizeof(shawRSA_AlgoID);
- algoName = shawRSA_AlgoID;
- break;
-
- case CTC_SHA256wRSA:
- algoSz = sizeof(sha256wRSA_AlgoID);
- algoName = sha256wRSA_AlgoID;
- break;
-
- case CTC_SHA384wRSA:
- algoSz = sizeof(sha384wRSA_AlgoID);
- algoName = sha384wRSA_AlgoID;
- break;
-
- case CTC_SHA512wRSA:
- algoSz = sizeof(sha512wRSA_AlgoID);
- algoName = sha512wRSA_AlgoID;
- break;
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case CTC_SHAwECDSA:
- algoSz = sizeof(shawECDSA_AlgoID);
- algoName = shawECDSA_AlgoID;
- break;
-
- case CTC_SHA256wECDSA:
- algoSz = sizeof(sha256wECDSA_AlgoID);
- algoName = sha256wECDSA_AlgoID;
- break;
-
- case CTC_SHA384wECDSA:
- algoSz = sizeof(sha384wECDSA_AlgoID);
- algoName = sha384wECDSA_AlgoID;
- break;
+ idSz = SetObjectId(algoSz, ID_Length);
+ seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray);
- case CTC_SHA512wECDSA:
- algoSz = sizeof(sha512wECDSA_AlgoID);
- algoName = sha512wECDSA_AlgoID;
- break;
- #endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Unknown Signature Algo");
- return 0;
- }
- }
- else if (type == keyType) { /* keyType */
- switch (algoOID) {
- #ifndef NO_RSA
- case RSAk:
- algoSz = sizeof(RSA_AlgoID);
- algoName = RSA_AlgoID;
- break;
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- algoSz = sizeof(ECC_AlgoID);
- algoName = ECC_AlgoID;
- tagSz = 0;
- break;
- #endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Unknown Key Algo");
- return 0;
- }
+ /* Copy only algo to output for DSA keys */
+ if (algoOID == DSAk && output) {
+ XMEMCPY(output, ID_Length, idSz);
+ XMEMCPY(output + idSz, algoName, algoSz);
+ if (tagSz == 2)
+ SetASNNull(&output[seqSz + idSz + algoSz]);
}
- else {
- WOLFSSL_MSG("Unknown Algo type");
- return 0;
+ else if (output) {
+ XMEMCPY(output, seqArray, seqSz);
+ XMEMCPY(output + seqSz, ID_Length, idSz);
+ XMEMCPY(output + seqSz + idSz, algoName, algoSz);
+ if (tagSz == 2)
+ SetASNNull(&output[seqSz + idSz + algoSz]);
}
- idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */
- seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray);
- /* +1 for object id, curveID of curveSz follows for ecc */
- seqArray[seqSz++] = ASN_OBJECT_ID;
-
- XMEMCPY(output, seqArray, seqSz);
- XMEMCPY(output + seqSz, ID_Length, idSz);
- XMEMCPY(output + seqSz + idSz, algoName, algoSz);
-
- return seqSz + idSz + algoSz;
+ if (algoOID == DSAk)
+ length = idSz + algoSz + tagSz;
+ else
+ length = seqSz + idSz + algoSz + tagSz;
+ return length;
}
@@ -2950,7 +6858,7 @@ word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz,
word32 encDigSz, algoSz, seqSz;
encDigSz = SetDigest(digest, digSz, digArray);
- algoSz = SetAlgoID(hashOID, algoArray, hashType, 0);
+ algoSz = SetAlgoID(hashOID, algoArray, oidHashType, 0);
seqSz = SetSequence(encDigSz + algoSz, seqArray);
XMEMCPY(out, seqArray, seqSz);
@@ -2961,288 +6869,569 @@ word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz,
}
+#ifndef NO_CERTS
+
int wc_GetCTC_HashOID(int type)
{
- switch (type) {
-#ifdef WOLFSSL_MD2
- case MD2:
- return MD2h;
-#endif
-#ifndef NO_MD5
- case MD5:
- return MD5h;
-#endif
-#ifndef NO_SHA
- case SHA:
- return SHAh;
-#endif
-#ifndef NO_SHA256
- case SHA256:
- return SHA256h;
-#endif
-#ifdef WOLFSSL_SHA384
- case SHA384:
- return SHA384h;
-#endif
-#ifdef WOLFSSL_SHA512
- case SHA512:
- return SHA512h;
-#endif
- default:
- return 0;
- };
+ int ret;
+ enum wc_HashType hType;
+
+ hType = wc_HashTypeConvert(type);
+ ret = wc_HashGetOID(hType);
+ if (ret < 0)
+ ret = 0; /* backwards compatibility */
+
+ return ret;
}
+void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId)
+{
+ if (sigCtx) {
+ XMEMSET(sigCtx, 0, sizeof(SignatureCtx));
+ sigCtx->devId = devId;
+ sigCtx->heap = heap;
+ }
+}
-/* return true (1) or false (0) for Confirmation */
-static int ConfirmSignature(const byte* buf, word32 bufSz,
- const byte* key, word32 keySz, word32 keyOID,
- const byte* sig, word32 sigSz, word32 sigOID,
- void* heap)
+void FreeSignatureCtx(SignatureCtx* sigCtx)
{
- int typeH = 0, digestSz = 0, ret = 0;
-#ifdef WOLFSSL_SMALL_STACK
- byte* digest;
-#else
- byte digest[MAX_DIGEST_SIZE];
-#endif
+ if (sigCtx == NULL)
+ return;
-#ifdef WOLFSSL_SMALL_STACK
- digest = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (digest == NULL)
- return 0; /* not confirmed */
+ if (sigCtx->digest) {
+ XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_DIGEST);
+ sigCtx->digest = NULL;
+ }
+#ifndef NO_RSA
+ if (sigCtx->plain) {
+ XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+ sigCtx->plain = NULL;
+ }
+#endif
+#ifndef NO_ASN_CRYPT
+ if (sigCtx->key.ptr) {
+ switch (sigCtx->keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ wc_FreeRsaKey(sigCtx->key.rsa);
+ XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA);
+ break;
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ wc_ecc_free(sigCtx->key.ecc);
+ XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC);
+ break;
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ wc_ed25519_free(sigCtx->key.ed25519);
+ XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519);
+ break;
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ wc_ed448_free(sigCtx->key.ed448);
+ XFREE(sigCtx->key.ed448, sigCtx->heap, DYNAMIC_TYPE_ED448);
+ break;
+ #endif /* HAVE_ED448 */
+ default:
+ break;
+ } /* switch (keyOID) */
+ sigCtx->key.ptr = NULL;
+ }
#endif
- (void)key;
- (void)keySz;
- (void)sig;
- (void)sigSz;
- (void)heap;
+ /* reset state, we are done */
+ sigCtx->state = SIG_STATE_BEGIN;
+}
+
+#ifndef NO_ASN_CRYPT
+static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
+ byte* digest, int* typeH, int* digestSz, int verify)
+{
+ int ret = 0;
+
+ (void)verify;
switch (sigOID) {
- #ifndef NO_MD5
- case CTC_MD5wRSA:
- if (wc_Md5Hash(buf, bufSz, digest) == 0) {
- typeH = MD5h;
- digestSz = MD5_DIGEST_SIZE;
- }
- break;
- #endif
#if defined(WOLFSSL_MD2)
case CTC_MD2wRSA:
- if (wc_Md2Hash(buf, bufSz, digest) == 0) {
- typeH = MD2h;
- digestSz = MD2_DIGEST_SIZE;
- }
+ if (!verify) {
+ ret = HASH_TYPE_E;
+ WOLFSSL_MSG("MD2 not supported for signing");
+ }
+ else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) {
+ *typeH = MD2h;
+ *digestSz = MD2_DIGEST_SIZE;
+ }
break;
#endif
+ #ifndef NO_MD5
+ case CTC_MD5wRSA:
+ if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) {
+ *typeH = MD5h;
+ *digestSz = WC_MD5_DIGEST_SIZE;
+ }
+ break;
+ #endif
#ifndef NO_SHA
case CTC_SHAwRSA:
case CTC_SHAwDSA:
case CTC_SHAwECDSA:
- if (wc_ShaHash(buf, bufSz, digest) == 0) {
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
- }
- break;
+ if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) {
+ *typeH = SHAh;
+ *digestSz = WC_SHA_DIGEST_SIZE;
+ }
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA224
+ case CTC_SHA224wRSA:
+ case CTC_SHA224wECDSA:
+ if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA224h;
+ *digestSz = WC_SHA224_DIGEST_SIZE;
+ }
+ break;
#endif
#ifndef NO_SHA256
case CTC_SHA256wRSA:
case CTC_SHA256wECDSA:
- if (wc_Sha256Hash(buf, bufSz, digest) == 0) {
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
- }
- break;
+ if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA256h;
+ *digestSz = WC_SHA256_DIGEST_SIZE;
+ }
+ break;
+ #endif
+ #ifdef WOLFSSL_SHA384
+ case CTC_SHA384wRSA:
+ case CTC_SHA384wECDSA:
+ if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA384h;
+ *digestSz = WC_SHA384_DIGEST_SIZE;
+ }
+ break;
#endif
#ifdef WOLFSSL_SHA512
case CTC_SHA512wRSA:
case CTC_SHA512wECDSA:
- if (wc_Sha512Hash(buf, bufSz, digest) == 0) {
- typeH = SHA512h;
- digestSz = SHA512_DIGEST_SIZE;
- }
- break;
+ if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) {
+ *typeH = SHA512h;
+ *digestSz = WC_SHA512_DIGEST_SIZE;
+ }
+ break;
#endif
- #ifdef WOLFSSL_SHA384
- case CTC_SHA384wRSA:
- case CTC_SHA384wECDSA:
- if (wc_Sha384Hash(buf, bufSz, digest) == 0) {
- typeH = SHA384h;
- digestSz = SHA384_DIGEST_SIZE;
- }
- break;
+ #ifdef HAVE_ED25519
+ case CTC_ED25519:
+ /* Hashes done in signing operation.
+ * Two dependent hashes with prefixes performed.
+ */
+ break;
+ #endif
+ #ifdef HAVE_ED448
+ case CTC_ED448:
+ /* Hashes done in signing operation.
+ * Two dependent hashes with prefixes performed.
+ */
+ break;
#endif
default:
- WOLFSSL_MSG("Verify Signautre has unsupported type");
+ ret = HASH_TYPE_E;
+ WOLFSSL_MSG("Hash for Signature has unsupported type");
}
-
- if (typeH == 0) {
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ return ret;
+}
+#endif /* !NO_ASN_CRYPT */
+
+/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */
+static int ConfirmSignature(SignatureCtx* sigCtx,
+ const byte* buf, word32 bufSz,
+ const byte* key, word32 keySz, word32 keyOID,
+ const byte* sig, word32 sigSz, word32 sigOID, byte* rsaKeyIdx)
+{
+ int ret = 0;
+#ifndef WOLFSSL_RENESAS_TSIP_TLS
+ (void)rsaKeyIdx;
#endif
- return 0; /* not confirmed */
+ if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL ||
+ keySz == 0 || sig == NULL || sigSz == 0) {
+ return BAD_FUNC_ARG;
}
- switch (keyOID) {
- #ifndef NO_RSA
- case RSAk:
+ (void)key;
+ (void)keySz;
+ (void)sig;
+ (void)sigSz;
+
+ WOLFSSL_ENTER("ConfirmSignature");
+
+#ifndef NO_ASN_CRYPT
+ switch (sigCtx->state) {
+ case SIG_STATE_BEGIN:
{
- word32 idx = 0;
- int encodedSigSz, verifySz;
- byte* out;
-#ifdef WOLFSSL_SMALL_STACK
- RsaKey* pubKey;
- byte* plain;
- byte* encodedSig;
-#else
- RsaKey pubKey[1];
- byte plain[MAX_ENCODED_SIG_SZ];
- byte encodedSig[MAX_ENCODED_SIG_SZ];
-#endif
+ sigCtx->keyOID = keyOID; /* must set early for cleanup */
-#ifdef WOLFSSL_SMALL_STACK
- pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
-
- if (pubKey == NULL || plain == NULL || encodedSig == NULL) {
- WOLFSSL_MSG("Failed to allocate memory at ConfirmSignature");
-
- if (pubKey)
- XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (plain)
- XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (encodedSig)
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-
- break; /* not confirmed */
+ sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap,
+ DYNAMIC_TYPE_DIGEST);
+ if (sigCtx->digest == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
}
-#endif
- if (sigSz > MAX_ENCODED_SIG_SZ) {
- WOLFSSL_MSG("Verify Signautre is too big");
+ sigCtx->state = SIG_STATE_HASH;
+ } /* SIG_STATE_BEGIN */
+ FALL_THROUGH;
+
+ case SIG_STATE_HASH:
+ {
+ ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest,
+ &sigCtx->typeH, &sigCtx->digestSz, 1);
+ if (ret != 0) {
+ goto exit_cs;
}
- else if (wc_InitRsaKey(pubKey, heap) != 0) {
- WOLFSSL_MSG("InitRsaKey failed");
+
+ sigCtx->state = SIG_STATE_KEY;
+ } /* SIG_STATE_HASH */
+ FALL_THROUGH;
+
+ case SIG_STATE_KEY:
+ {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ {
+ word32 idx = 0;
+
+ sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey),
+ sigCtx->heap, DYNAMIC_TYPE_RSA);
+ sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+ sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+ if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap,
+ sigCtx->devId)) != 0) {
+ goto exit_cs;
+ }
+ if (sigSz > MAX_ENCODED_SIG_SZ) {
+ WOLFSSL_MSG("Verify Signature is too big");
+ ERROR_OUT(BUFFER_E, exit_cs);
+ }
+ if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa,
+ keySz)) != 0) {
+ WOLFSSL_MSG("ASN Key decode error RSA");
+ goto exit_cs;
+ }
+ XMEMCPY(sigCtx->plain, sig, sigSz);
+ sigCtx->out = NULL;
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev;
+ #endif
+ break;
+ }
+ #endif /* !NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ {
+ word32 idx = 0;
+
+ sigCtx->verify = 0;
+ sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key),
+ sigCtx->heap, DYNAMIC_TYPE_ECC);
+ if (sigCtx->key.ecc == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap,
+ sigCtx->devId)) < 0) {
+ goto exit_cs;
+ }
+ ret = wc_EccPublicKeyDecode(key, &idx, sigCtx->key.ecc,
+ keySz);
+ if (ret < 0) {
+ WOLFSSL_MSG("ASN Key import error ECC");
+ goto exit_cs;
+ }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev;
+ #endif
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ sigCtx->verify = 0;
+ sigCtx->key.ed25519 = (ed25519_key*)XMALLOC(
+ sizeof(ed25519_key), sigCtx->heap,
+ DYNAMIC_TYPE_ED25519);
+ if (sigCtx->key.ed25519 == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) {
+ goto exit_cs;
+ }
+ if ((ret = wc_ed25519_import_public(key, keySz,
+ sigCtx->key.ed25519)) < 0) {
+ WOLFSSL_MSG("ASN Key import error ED25519");
+ goto exit_cs;
+ }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.ed25519->asyncDev;
+ #endif
+ break;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ sigCtx->verify = 0;
+ sigCtx->key.ed448 = (ed448_key*)XMALLOC(
+ sizeof(ed448_key), sigCtx->heap,
+ DYNAMIC_TYPE_ED448);
+ if (sigCtx->key.ed448 == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
+ }
+ if ((ret = wc_ed448_init(sigCtx->key.ed448)) < 0) {
+ goto exit_cs;
+ }
+ if ((ret = wc_ed448_import_public(key, keySz,
+ sigCtx->key.ed448)) < 0) {
+ WOLFSSL_MSG("ASN Key import error ED448");
+ goto exit_cs;
+ }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ sigCtx->asyncDev = &sigCtx->key.ed448->asyncDev;
+ #endif
+ break;
+ }
+ #endif
+ default:
+ WOLFSSL_MSG("Verify Key type unknown");
+ ret = ASN_UNKNOWN_OID_E;
+ break;
+ } /* switch (keyOID) */
+
+ if (ret != 0) {
+ goto exit_cs;
}
- else if (wc_RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) {
- WOLFSSL_MSG("ASN Key decode error RSA");
+
+ sigCtx->state = SIG_STATE_DO;
+
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) {
+ /* make sure event is initialized */
+ WOLF_EVENT* event = &sigCtx->asyncDev->event;
+ ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL,
+ sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN);
}
- else {
- XMEMCPY(plain, sig, sigSz);
+ #endif
+ } /* SIG_STATE_KEY */
+ FALL_THROUGH;
- if ((verifySz = wc_RsaSSL_VerifyInline(plain, sigSz, &out,
- pubKey)) < 0) {
- WOLFSSL_MSG("Rsa SSL verify error");
+ case SIG_STATE_DO:
+ {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ {
+ #ifdef HAVE_PK_CALLBACKS
+ if (sigCtx->pkCbRsa) {
+ ret = sigCtx->pkCbRsa(
+ sigCtx->plain, sigSz, &sigCtx->out,
+ key, keySz,
+ sigCtx->pkCtxRsa);
+ }
+ else
+ #endif /* HAVE_PK_CALLBACKS */
+ {
+ #ifdef WOLFSSL_RENESAS_TSIP_TLS
+ if (rsaKeyIdx != NULL)
+ {
+ ret = tsip_tls_CertVerify(buf, bufSz, sigCtx->plain,
+ sigSz,
+ sigCtx->pubkey_n_start - sigCtx->certBegin,
+ sigCtx->pubkey_n_len - 1,
+ sigCtx->pubkey_e_start - sigCtx->certBegin,
+ sigCtx->pubkey_e_len - 1,
+ rsaKeyIdx);
+
+ if (ret == 0){
+ sigCtx->verifyByTSIP = 1;
+ ret = 0;
+ } else {
+ WOLFSSL_MSG("RSA Verify by tsip didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ } else
+ #endif
+ ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz,
+ &sigCtx->out, sigCtx->key.rsa);
+ }
+ break;
}
- else {
- /* make sure we're right justified */
- encodedSigSz =
- wc_EncodeSignature(encodedSig, digest, digestSz, typeH);
- if (encodedSigSz != verifySz ||
- XMEMCMP(out, encodedSig, encodedSigSz) != 0) {
- WOLFSSL_MSG("Rsa SSL verify match encode error");
+ #endif /* !NO_RSA */
+ #if defined(HAVE_ECC)
+ case ECDSAk:
+ {
+ #ifdef HAVE_PK_CALLBACKS
+ if (sigCtx->pkCbEcc) {
+ ret = sigCtx->pkCbEcc(
+ sig, sigSz,
+ sigCtx->digest, sigCtx->digestSz,
+ key, keySz, &sigCtx->verify,
+ sigCtx->pkCtxEcc);
}
else
- ret = 1; /* match */
-
- #ifdef WOLFSSL_DEBUG_ENCODING
+ #endif /* HAVE_PK_CALLBACKS */
{
- int x;
-
- printf("wolfssl encodedSig:\n");
+ ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest,
+ sigCtx->digestSz, &sigCtx->verify,
+ sigCtx->key.ecc);
+ }
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz,
+ &sigCtx->verify, sigCtx->key.ed25519);
+ break;
+ }
+ #endif
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ ret = wc_ed448_verify_msg(sig, sigSz, buf, bufSz,
+ &sigCtx->verify, sigCtx->key.ed448,
+ NULL, 0);
+ break;
+ }
+ #endif
+ default:
+ break;
+ } /* switch (keyOID) */
- for (x = 0; x < encodedSigSz; x++) {
- printf("%02x ", encodedSig[x]);
- if ( (x % 16) == 15)
- printf("\n");
- }
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
+ goto exit_cs;
+ }
+ #endif
- printf("\n");
- printf("actual digest:\n");
+ if (ret < 0) {
+ /* treat all RSA errors as ASN_SIG_CONFIRM_E */
+ ret = ASN_SIG_CONFIRM_E;
+ goto exit_cs;
+ }
- for (x = 0; x < verifySz; x++) {
- printf("%02x ", out[x]);
- if ( (x % 16) == 15)
- printf("\n");
- }
+ sigCtx->state = SIG_STATE_CHECK;
+ } /* SIG_STATE_DO */
+ FALL_THROUGH;
- printf("\n");
+ case SIG_STATE_CHECK:
+ {
+ switch (keyOID) {
+ #ifndef NO_RSA
+ case RSAk:
+ {
+ int encodedSigSz, verifySz;
+ #ifdef WOLFSSL_RENESAS_TSIP
+ if (sigCtx->verifyByTSIP == 1) break;
+ #endif
+ #ifdef WOLFSSL_SMALL_STACK
+ byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+ sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (encodedSig == NULL) {
+ ERROR_OUT(MEMORY_E, exit_cs);
}
- #endif /* WOLFSSL_DEBUG_ENCODING */
+ #else
+ byte encodedSig[MAX_ENCODED_SIG_SZ];
+ #endif
- }
+ verifySz = ret;
- }
+ /* make sure we're right justified */
+ encodedSigSz = wc_EncodeSignature(encodedSig,
+ sigCtx->digest, sigCtx->digestSz, sigCtx->typeH);
+ if (encodedSigSz == verifySz && sigCtx->out != NULL &&
+ XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("RSA SSL verify match encode error");
+ ret = ASN_SIG_CONFIRM_E;
+ }
- wc_FreeRsaKey(pubKey);
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ break;
+ }
+ #endif /* NO_RSA */
+ #ifdef HAVE_ECC
+ case ECDSAk:
+ {
+ if (sigCtx->verify == 1) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("ECC Verify didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ break;
+ }
+ #endif /* HAVE_ECC */
+ #ifdef HAVE_ED25519
+ case ED25519k:
+ {
+ if (sigCtx->verify == 1) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("ED25519 Verify didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ break;
+ }
+ #endif /* HAVE_ED25519 */
+ #ifdef HAVE_ED448
+ case ED448k:
+ {
+ if (sigCtx->verify == 1) {
+ ret = 0;
+ }
+ else {
+ WOLFSSL_MSG("ED448 Verify didn't match");
+ ret = ASN_SIG_CONFIRM_E;
+ }
+ break;
+ }
+ #endif /* HAVE_ED448 */
+ default:
+ break;
+ } /* switch (keyOID) */
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
break;
- }
+ } /* SIG_STATE_CHECK */
+ } /* switch (sigCtx->state) */
- #endif /* NO_RSA */
- #ifdef HAVE_ECC
- case ECDSAk:
- {
- int verify = 0;
-#ifdef WOLFSSL_SMALL_STACK
- ecc_key* pubKey;
-#else
- ecc_key pubKey[1];
-#endif
+exit_cs:
-#ifdef WOLFSSL_SMALL_STACK
- pubKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (pubKey == NULL) {
- WOLFSSL_MSG("Failed to allocate pubKey");
- break; /* not confirmed */
- }
-#endif
+#endif /* !NO_ASN_CRYPT */
- if (wc_ecc_init(pubKey) < 0) {
- WOLFSSL_MSG("Failed to initialize key");
- break; /* not confirmed */
- }
- if (wc_ecc_import_x963(key, keySz, pubKey) < 0) {
- WOLFSSL_MSG("ASN Key import error ECC");
- }
- else {
- if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify,
- pubKey) != 0) {
- WOLFSSL_MSG("ECC verify hash error");
- }
- else if (1 != verify) {
- WOLFSSL_MSG("ECC Verify didn't match");
- } else
- ret = 1; /* match */
+ (void)keyOID;
+ (void)sigOID;
- }
- wc_ecc_free(pubKey);
+ WOLFSSL_LEAVE("ConfirmSignature", ret);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
- break;
- }
- #endif /* HAVE_ECC */
- default:
- WOLFSSL_MSG("Verify Key type unknown");
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E)
+ return ret;
#endif
+ FreeSignatureCtx(sigCtx);
+
return ret;
}
@@ -3250,7 +7439,7 @@ static int ConfirmSignature(const byte* buf, word32 bufSz,
#ifndef IGNORE_NAME_CONSTRAINTS
static int MatchBaseName(int type, const char* name, int nameSz,
- const char* base, int baseSz)
+ const char* base, int baseSz)
{
if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 ||
name[0] == '.' || nameSz < baseSz ||
@@ -3302,7 +7491,7 @@ static int MatchBaseName(int type, const char* name, int nameSz,
}
while (nameSz > 0) {
- if (XTOLOWER((unsigned char)*name++) !=
+ if (XTOLOWER((unsigned char)*name++) !=
XTOLOWER((unsigned char)*base++))
return 0;
nameSz--;
@@ -3322,34 +7511,44 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
Base_entry* base = signer->excludedNames;
while (base != NULL) {
- if (base->type == ASN_DNS_TYPE) {
- DNS_entry* name = cert->altNames;
- while (name != NULL) {
- if (MatchBaseName(ASN_DNS_TYPE,
- name->name, (int)XSTRLEN(name->name),
- base->name, base->nameSz))
- return 0;
- name = name->next;
+ switch (base->type) {
+ case ASN_DNS_TYPE:
+ {
+ DNS_entry* name = cert->altNames;
+ while (name != NULL) {
+ if (MatchBaseName(ASN_DNS_TYPE,
+ name->name, name->len,
+ base->name, base->nameSz)) {
+ return 0;
+ }
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_RFC822_TYPE) {
- DNS_entry* name = cert->altEmailNames;
- while (name != NULL) {
- if (MatchBaseName(ASN_RFC822_TYPE,
- name->name, (int)XSTRLEN(name->name),
- base->name, base->nameSz))
- return 0;
-
- name = name->next;
+ case ASN_RFC822_TYPE:
+ {
+ DNS_entry* name = cert->altEmailNames;
+ while (name != NULL) {
+ if (MatchBaseName(ASN_RFC822_TYPE,
+ name->name, name->len,
+ base->name, base->nameSz)) {
+ return 0;
+ }
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_DIR_TYPE) {
- if (cert->subjectRawLen == base->nameSz &&
- XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
-
- return 0;
+ case ASN_DIR_TYPE:
+ {
+ /* allow permitted dirName smaller than actual subject */
+ if (cert->subjectRawLen >= base->nameSz &&
+ XMEMCMP(cert->subjectRaw, base->name,
+ base->nameSz) == 0) {
+ return 0;
+ }
+ break;
}
- }
+ }; /* switch */
base = base->next;
}
}
@@ -3365,47 +7564,56 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
Base_entry* base = signer->permittedNames;
while (base != NULL) {
- if (base->type == ASN_DNS_TYPE) {
- DNS_entry* name = cert->altNames;
+ switch (base->type) {
+ case ASN_DNS_TYPE:
+ {
+ DNS_entry* name = cert->altNames;
- if (name != NULL)
- needDns = 1;
+ if (name != NULL)
+ needDns = 1;
- while (name != NULL) {
- matchDns = MatchBaseName(ASN_DNS_TYPE,
- name->name, (int)XSTRLEN(name->name),
+ while (name != NULL) {
+ matchDns = MatchBaseName(ASN_DNS_TYPE,
+ name->name, name->len,
base->name, base->nameSz);
- name = name->next;
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_RFC822_TYPE) {
- DNS_entry* name = cert->altEmailNames;
+ case ASN_RFC822_TYPE:
+ {
+ DNS_entry* name = cert->altEmailNames;
- if (name != NULL)
- needEmail = 1;
+ if (name != NULL)
+ needEmail = 1;
- while (name != NULL) {
- matchEmail = MatchBaseName(ASN_DNS_TYPE,
- name->name, (int)XSTRLEN(name->name),
+ while (name != NULL) {
+ matchEmail = MatchBaseName(ASN_DNS_TYPE,
+ name->name, name->len,
base->name, base->nameSz);
- name = name->next;
+ name = name->next;
+ }
+ break;
}
- }
- else if (base->type == ASN_DIR_TYPE) {
- needDir = 1;
- if (cert->subjectRaw != NULL &&
- cert->subjectRawLen == base->nameSz &&
- XMEMCMP(cert->subjectRaw, base->name, base->nameSz) == 0) {
-
- matchDir = 1;
+ case ASN_DIR_TYPE:
+ {
+ /* allow permitted dirName smaller than actual subject */
+ needDir = 1;
+ if (cert->subjectRaw != NULL &&
+ cert->subjectRawLen >= base->nameSz &&
+ XMEMCMP(cert->subjectRaw, base->name,
+ base->nameSz) == 0) {
+ matchDir = 1;
+ }
+ break;
}
- }
+ } /* switch */
base = base->next;
}
- if ((needDns && !matchDns) || (needEmail && !matchEmail) ||
- (needDir && !matchDir)) {
-
+ if ((needDns && !matchDns) ||
+ (needEmail && !matchEmail) ||
+ (needDir && !matchDir)) {
return 0;
}
}
@@ -3415,8 +7623,7 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
#endif /* IGNORE_NAME_CONSTRAINTS */
-
-static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
+static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0;
@@ -3428,10 +7635,17 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
+ if (length == 0) {
+ /* RFC 5280 4.2.1.6. Subject Alternative Name
+ If the subjectAltName extension is present, the sequence MUST
+ contain at least one entry. */
+ return ASN_PARSE_E;
+ }
+
cert->weOwnAltNames = 1;
while (length > 0) {
- byte b = input[idx++];
+ byte b = input[idx++];
length--;
@@ -3452,17 +7666,18 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
DYNAMIC_TYPE_ALTNAME);
if (dnsEntry == NULL) {
WOLFSSL_MSG("\tOut of Memory");
- return ASN_PARSE_E;
+ return MEMORY_E;
}
+ dnsEntry->type = ASN_DNS_TYPE;
dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
DYNAMIC_TYPE_ALTNAME);
if (dnsEntry->name == NULL) {
WOLFSSL_MSG("\tOut of Memory");
XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
- return ASN_PARSE_E;
+ return MEMORY_E;
}
-
+ dnsEntry->len = strLen;
XMEMCPY(dnsEntry->name, &input[idx], strLen);
dnsEntry->name[strLen] = '\0';
@@ -3472,7 +7687,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
length -= strLen;
idx += strLen;
}
-#ifndef IGNORE_NAME_CONSTRAINTS
+ #ifndef IGNORE_NAME_CONSTRAINTS
else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
DNS_entry* emailEntry;
int strLen;
@@ -3488,17 +7703,18 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
DYNAMIC_TYPE_ALTNAME);
if (emailEntry == NULL) {
WOLFSSL_MSG("\tOut of Memory");
- return ASN_PARSE_E;
+ return MEMORY_E;
}
+ emailEntry->type = ASN_RFC822_TYPE;
emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
DYNAMIC_TYPE_ALTNAME);
if (emailEntry->name == NULL) {
WOLFSSL_MSG("\tOut of Memory");
XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
- return ASN_PARSE_E;
+ return MEMORY_E;
}
-
+ emailEntry->len = strLen;
XMEMCPY(emailEntry->name, &input[idx], strLen);
emailEntry->name[strLen] = '\0';
@@ -3508,6 +7724,120 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
length -= strLen;
idx += strLen;
}
+ else if (b == (ASN_CONTEXT_SPECIFIC | ASN_URI_TYPE)) {
+ DNS_entry* uriEntry;
+ int strLen;
+ word32 lenStartIdx = idx;
+
+ WOLFSSL_MSG("\tPutting URI into list but not using");
+ if (GetLength(input, &idx, &strLen, sz) < 0) {
+ WOLFSSL_MSG("\tfail: str length");
+ return ASN_PARSE_E;
+ }
+ length -= (idx - lenStartIdx);
+
+ /* check that strLen at index is not past input buffer */
+ if (strLen + (int)idx > sz) {
+ return BUFFER_E;
+ }
+
+ #ifndef WOLFSSL_NO_ASN_STRICT
+ /* Verify RFC 5280 Sec 4.2.1.6 rule:
+ "The name MUST NOT be a relative URI" */
+
+ {
+ int i;
+
+ /* skip past scheme (i.e http,ftp,...) finding first ':' char */
+ for (i = 0; i < strLen; i++) {
+ if (input[idx + i] == ':') {
+ break;
+ }
+ if (input[idx + i] == '/') {
+ i = strLen; /* error, found relative path since '/' was
+ * encountered before ':'. Returning error
+ * value in next if statement. */
+ }
+ }
+
+ /* test if no ':' char was found and test that the next two
+ * chars are // to match the pattern "://" */
+ if (i >= strLen - 2 || (input[idx + i + 1] != '/' ||
+ input[idx + i + 2] != '/')) {
+ WOLFSSL_MSG("\tAlt Name must be absolute URI");
+ return ASN_ALT_NAME_E;
+ }
+ }
+ #endif
+
+ uriEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (uriEntry == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ return MEMORY_E;
+ }
+
+ uriEntry->type = ASN_URI_TYPE;
+ uriEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (uriEntry->name == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ XFREE(uriEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
+ return MEMORY_E;
+ }
+ uriEntry->len = strLen;
+ XMEMCPY(uriEntry->name, &input[idx], strLen);
+ uriEntry->name[strLen] = '\0';
+
+ uriEntry->next = cert->altNames;
+ cert->altNames = uriEntry;
+
+ length -= strLen;
+ idx += strLen;
+ }
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+ else if (b == (ASN_CONTEXT_SPECIFIC | ASN_IP_TYPE)) {
+ DNS_entry* ipAddr;
+ int strLen;
+ word32 lenStartIdx = idx;
+ WOLFSSL_MSG("Decoding Subject Alt. Name: IP Address");
+
+ if (GetLength(input, &idx, &strLen, sz) < 0) {
+ WOLFSSL_MSG("\tfail: str length");
+ return ASN_PARSE_E;
+ }
+ length -= (idx - lenStartIdx);
+ /* check that strLen at index is not past input buffer */
+ if (strLen + (int)idx > sz) {
+ return BUFFER_E;
+ }
+
+ ipAddr = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (ipAddr == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ return MEMORY_E;
+ }
+
+ ipAddr->type = ASN_IP_TYPE;
+ ipAddr->name = (char*)XMALLOC(strLen + 1, cert->heap,
+ DYNAMIC_TYPE_ALTNAME);
+ if (ipAddr->name == NULL) {
+ WOLFSSL_MSG("\tOut of Memory");
+ XFREE(ipAddr, cert->heap, DYNAMIC_TYPE_ALTNAME);
+ return MEMORY_E;
+ }
+ ipAddr->len = strLen;
+ XMEMCPY(ipAddr->name, &input[idx], strLen);
+ ipAddr->name[strLen] = '\0';
+
+ ipAddr->next = cert->altNames;
+ cert->altNames = ipAddr;
+
+ length -= strLen;
+ idx += strLen;
+ }
+#endif /* WOLFSSL_QT || OPENSSL_ALL */
#endif /* IGNORE_NAME_CONSTRAINTS */
#ifdef WOLFSSL_SEP
else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE))
@@ -3515,6 +7845,8 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
int strLen;
word32 lenStartIdx = idx;
word32 oid = 0;
+ int ret;
+ byte tag;
if (GetLength(input, &idx, &strLen, sz) < 0) {
WOLFSSL_MSG("\tfail: other name length");
@@ -3523,7 +7855,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
/* Consume the rest of this sequence. */
length -= (strLen + idx - lenStartIdx);
- if (GetObjectId(input, &idx, &oid, sz) < 0) {
+ if (GetObjectId(input, &idx, &oid, oidCertAltNameType, sz) < 0) {
WOLFSSL_MSG("\tbad OID");
return ASN_PARSE_E;
}
@@ -3533,7 +7865,11 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
- if (input[idx++] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
WOLFSSL_MSG("\twrong type");
return ASN_PARSE_E;
}
@@ -3548,17 +7884,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
- if (input[idx++] != ASN_OBJECT_ID) {
- WOLFSSL_MSG("\texpected OID");
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &idx, &strLen, sz) < 0) {
- WOLFSSL_MSG("\tfailed: str len");
- return ASN_PARSE_E;
+ ret = GetASNObjectId(input, &idx, &strLen, sz);
+ if (ret != 0) {
+ WOLFSSL_MSG("\tbad OID");
+ return ret;
}
- cert->hwType = (byte*)XMALLOC(strLen, cert->heap, 0);
+ cert->hwType = (byte*)XMALLOC(strLen, cert->heap,
+ DYNAMIC_TYPE_X509_EXT);
if (cert->hwType == NULL) {
WOLFSSL_MSG("\tOut of Memory");
return MEMORY_E;
@@ -3568,17 +7901,12 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
cert->hwTypeSz = strLen;
idx += strLen;
- if (input[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\texpected Octet String");
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &idx, &strLen, sz) < 0) {
- WOLFSSL_MSG("\tfailed: str len");
- return ASN_PARSE_E;
- }
+ ret = GetOctetString(input, &idx, &strLen, sz);
+ if (ret < 0)
+ return ret;
- cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, 0);
+ cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap,
+ DYNAMIC_TYPE_X509_EXT);
if (cert->hwSerialNum == NULL) {
WOLFSSL_MSG("\tOut of Memory");
return MEMORY_E;
@@ -3589,7 +7917,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
cert->hwSerialNumSz = strLen;
idx += strLen;
}
-#endif /* WOLFSSL_SEP */
+ #endif /* WOLFSSL_SEP */
else {
int strLen;
word32 lenStartIdx = idx;
@@ -3607,13 +7935,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert)
return 0;
}
-
-static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
+static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0;
+ int ret;
WOLFSSL_ENTER("DecodeBasicCaConstraint");
+
if (GetSequence(input, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: bad SEQUENCE");
return ASN_PARSE_E;
@@ -3625,40 +7954,35 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
/* If the basic ca constraint is false, this extension may be named, but
* left empty. So, if the length is 0, just return. */
- if (input[idx++] != ASN_BOOLEAN)
- {
- WOLFSSL_MSG("\tfail: constraint not BOOLEAN");
- return ASN_PARSE_E;
- }
+ ret = GetBoolean(input, &idx, sz);
- if (GetLength(input, &idx, &length, sz) < 0)
- {
- WOLFSSL_MSG("\tfail: length");
- return ASN_PARSE_E;
+#ifndef WOLFSSL_X509_BASICCONS_INT
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN");
+ return ret;
}
- if (input[idx++])
- cert->isCA = 1;
-
- #ifdef OPENSSL_EXTRA
- /* If there isn't any more data, return. */
- if (idx >= (word32)sz)
- return 0;
-
- /* Anything left should be the optional pathlength */
- if (input[idx++] != ASN_INTEGER) {
- WOLFSSL_MSG("\tfail: pathlen not INTEGER");
- return ASN_PARSE_E;
- }
+ cert->isCA = (byte)ret;
+#else
+ if (ret < 0) {
+ if(input[idx] == ASN_INTEGER) {
+ /* For OpenSSL compatibility, if ASN_INTEGER it is valid format */
+ cert->isCA = FALSE;
+ } else return ret;
+ } else
+ cert->isCA = (byte)ret;
+#endif
- if (input[idx++] != 1) {
- WOLFSSL_MSG("\tfail: pathlen too long");
- return ASN_PARSE_E;
- }
+ /* If there isn't any more data, return. */
+ if (idx >= (word32)sz) {
+ return 0;
+ }
- cert->pathLength = input[idx];
- cert->extBasicConstPlSet = 1;
- #endif /* OPENSSL_EXTRA */
+ ret = GetInteger7Bit(input, &idx, sz);
+ if (ret < 0)
+ return ret;
+ cert->pathLength = (byte)ret;
+ cert->pathLengthSet = 1;
return 0;
}
@@ -3669,10 +7993,11 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert)
#define GENERALNAME_URI 6
/* From RFC3280 SS4.2.1.7, GeneralName */
-static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
+static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert)
{
- word32 idx = 0;
+ word32 idx = 0, localIdx;
int length = 0;
+ byte tag = 0;
WOLFSSL_ENTER("DecodeCrlDist");
@@ -3687,20 +8012,26 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
/* The Distribution Point has three explicit optional members
* First check for a DistributionPointName
*/
- if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
- if (input[idx] ==
- (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME))
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED |
+ CRLDP_FULL_NAME))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
- if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
@@ -3714,14 +8045,17 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
/* This isn't a URI, skip it. */
idx += length;
}
- else
+ else {
/* This isn't a FULLNAME, skip it. */
idx += length;
+ }
}
/* Check for reasonFlags */
+ localIdx = idx;
if (idx < (word32)sz &&
- input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
+ GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
@@ -3730,8 +8064,10 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
}
/* Check for cRLIssuer */
+ localIdx = idx;
if (idx < (word32)sz &&
- input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
+ GetASNTag(input, &localIdx, &tag, sz) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2))
{
idx++;
if (GetLength(input, &idx, &length, sz) < 0)
@@ -3749,15 +8085,16 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert)
}
-static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
+static int DecodeAuthInfo(const byte* input, int sz, DecodedCert* cert)
/*
- * Read the first of the Authority Information Access records. If there are
+ * Read Authority Information Access records. If there are
* any issues, return without saving the record.
*/
{
word32 idx = 0;
int length = 0;
- byte b;
+ int count = 0;
+ byte b = 0;
word32 oid;
WOLFSSL_ENTER("DecodeAuthInfo");
@@ -3766,27 +8103,43 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
if (GetSequence(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
- while (idx < (word32)sz) {
+ while ((idx < (word32)sz) && (count < MAX_AIA_SZ)) {
/* Unwrap a single AIA */
if (GetSequence(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
oid = 0;
- if (GetObjectId(input, &idx, &oid, sz) < 0)
+ if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0)
return ASN_PARSE_E;
/* Only supporting URIs right now. */
- b = input[idx++];
+ if (GetASNTag(input, &idx, &b, sz) < 0)
+ return ASN_PARSE_E;
+
if (GetLength(input, &idx, &length, sz) < 0)
return ASN_PARSE_E;
+ /* Set ocsp entry */
if (b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI) &&
oid == AIA_OCSP_OID)
{
cert->extAuthInfoSz = length;
cert->extAuthInfo = input + idx;
+ count++;
+ #if !defined(OPENSSL_ALL) || !defined(WOLFSSL_QT)
break;
+ #endif
+ }
+ #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
+ /* Set CaIssuers entry */
+ else if ((b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) &&
+ oid == AIA_CA_ISSUER_OID)
+ {
+ cert->extAuthInfoCaIssuerSz = length;
+ cert->extAuthInfoCaIssuer = input + idx;
+ count++;
}
+ #endif
idx += length;
}
@@ -3794,10 +8147,11 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert)
}
-static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
+static int DecodeAuthKeyId(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0, ret = 0;
+ byte tag;
WOLFSSL_ENTER("DecodeAuthKeyId");
@@ -3806,124 +8160,107 @@ static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert)
return ASN_PARSE_E;
}
- if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | 0)) {
WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
+ cert->extAuthKeyIdSet = 0;
return 0;
}
- if (GetLength(input, &idx, &length, sz) < 0) {
+ if (GetLength(input, &idx, &length, sz) <= 0) {
WOLFSSL_MSG("\tfail: extension data length");
return ASN_PARSE_E;
}
- #ifdef OPENSSL_EXTRA
- cert->extAuthKeyIdSrc = &input[idx];
- cert->extAuthKeyIdSz = length;
- #endif /* OPENSSL_EXTRA */
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extAuthKeyIdSrc = &input[idx];
+ cert->extAuthKeyIdSz = length;
+#endif /* OPENSSL_EXTRA */
if (length == KEYID_SIZE) {
XMEMCPY(cert->extAuthKeyId, input + idx, length);
}
- else {
- #ifdef NO_SHA
- ret = wc_Sha256Hash(input + idx, length, cert->extAuthKeyId);
- #else
- ret = wc_ShaHash(input + idx, length, cert->extAuthKeyId);
- #endif
- }
+ else
+ ret = CalcHashId(input + idx, length, cert->extAuthKeyId);
return ret;
}
-static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert)
+static int DecodeSubjKeyId(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0, ret = 0;
WOLFSSL_ENTER("DecodeSubjKeyId");
- if (input[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\tfail: should be an OCTET STRING");
+ if (sz <= 0)
return ASN_PARSE_E;
- }
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: extension data length");
- return ASN_PARSE_E;
- }
+ ret = GetOctetString(input, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
- #ifdef OPENSSL_EXTRA
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extSubjKeyIdSrc = &input[idx];
cert->extSubjKeyIdSz = length;
#endif /* OPENSSL_EXTRA */
- if (length == SIGNER_DIGEST_SIZE) {
+ if (length == KEYID_SIZE) {
XMEMCPY(cert->extSubjKeyId, input + idx, length);
}
- else {
- #ifdef NO_SHA
- ret = wc_Sha256Hash(input + idx, length, cert->extSubjKeyId);
- #else
- ret = wc_ShaHash(input + idx, length, cert->extSubjKeyId);
- #endif
- }
+ else
+ ret = CalcHashId(input + idx, length, cert->extSubjKeyId);
return ret;
}
-static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert)
+static int DecodeKeyUsage(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length;
- byte unusedBits;
+ int ret;
WOLFSSL_ENTER("DecodeKeyUsage");
- if (input[idx++] != ASN_BIT_STRING) {
- WOLFSSL_MSG("\tfail: key usage expected bit string");
- return ASN_PARSE_E;
- }
-
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: key usage bad length");
- return ASN_PARSE_E;
- }
-
- unusedBits = input[idx++];
- length--;
+ ret = CheckBitString(input, &idx, &length, sz, 0, NULL);
+ if (ret != 0)
+ return ret;
- if (length == 2) {
- cert->extKeyUsage = (word16)((input[idx] << 8) | input[idx+1]);
- cert->extKeyUsage >>= unusedBits;
- }
- else if (length == 1)
- cert->extKeyUsage = (word16)(input[idx] << 1);
+ cert->extKeyUsage = (word16)(input[idx]);
+ if (length == 2)
+ cert->extKeyUsage |= (word16)(input[idx+1] << 8);
return 0;
}
-static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
+static int DecodeExtKeyUsage(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0, oid;
- int length;
+ int length, ret;
- WOLFSSL_ENTER("DecodeExtKeyUsage");
+ WOLFSSL_MSG("DecodeExtKeyUsage");
if (GetSequence(input, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
- #ifdef OPENSSL_EXTRA
- cert->extExtKeyUsageSrc = input + idx;
- cert->extExtKeyUsageSz = length;
- #endif
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extExtKeyUsageSrc = input + idx;
+ cert->extExtKeyUsageSz = length;
+#endif
while (idx < (word32)sz) {
- if (GetObjectId(input, &idx, &oid, sz) < 0)
- return ASN_PARSE_E;
+ ret = GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz);
+ if (ret == ASN_UNKNOWN_OID_E)
+ continue;
+ else if (ret < 0)
+ return ret;
switch (oid) {
case EKU_ANY_OID:
@@ -3935,14 +8272,23 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
case EKU_CLIENT_AUTH_OID:
cert->extExtKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
break;
+ case EKU_CODESIGNING_OID:
+ cert->extExtKeyUsage |= EXTKEYUSE_CODESIGN;
+ break;
+ case EKU_EMAILPROTECT_OID:
+ cert->extExtKeyUsage |= EXTKEYUSE_EMAILPROT;
+ break;
+ case EKU_TIMESTAMP_OID:
+ cert->extExtKeyUsage |= EXTKEYUSE_TIMESTAMP;
+ break;
case EKU_OCSP_SIGN_OID:
cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN;
break;
}
- #ifdef OPENSSL_EXTRA
- cert->extExtKeyUsageCount++;
- #endif
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extExtKeyUsageCount++;
+ #endif
}
return 0;
@@ -3950,7 +8296,9 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert)
#ifndef IGNORE_NAME_CONSTRAINTS
-static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
+#define ASN_TYPE_MASK 0xF
+static int DecodeSubtree(const byte* input, int sz,
+ Base_entry** head, void* heap)
{
word32 idx = 0;
@@ -3959,27 +8307,37 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
while (idx < (word32)sz) {
int seqLength, strLength;
word32 nameIdx;
- byte b;
+ byte b, bType;
if (GetSequence(input, &idx, &seqLength, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
-
nameIdx = idx;
b = input[nameIdx++];
+
if (GetLength(input, &nameIdx, &strLength, sz) <= 0) {
WOLFSSL_MSG("\tinvalid length");
return ASN_PARSE_E;
}
- if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE) ||
- b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE) ||
- b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) {
+ /* Get type, LSB 4-bits */
+ bType = (b & ASN_TYPE_MASK);
+
+ if (bType == ASN_DNS_TYPE || bType == ASN_RFC822_TYPE ||
+ bType == ASN_DIR_TYPE) {
+ Base_entry* entry;
- Base_entry* entry = (Base_entry*)XMALLOC(sizeof(Base_entry),
- heap, DYNAMIC_TYPE_ALTNAME);
+ /* if constructed has leading sequence */
+ if (b & ASN_CONSTRUCTED) {
+ if (GetSequence(input, &nameIdx, &strLength, sz) < 0) {
+ WOLFSSL_MSG("\tfail: constructed be a SEQUENCE");
+ return ASN_PARSE_E;
+ }
+ }
+ entry = (Base_entry*)XMALLOC(sizeof(Base_entry), heap,
+ DYNAMIC_TYPE_ALTNAME);
if (entry == NULL) {
WOLFSSL_MSG("allocate error");
return MEMORY_E;
@@ -3988,12 +8346,13 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME);
if (entry->name == NULL) {
WOLFSSL_MSG("allocate error");
+ XFREE(entry, heap, DYNAMIC_TYPE_ALTNAME);
return MEMORY_E;
}
XMEMCPY(entry->name, &input[nameIdx], strLength);
entry->nameSz = strLength;
- entry->type = b & 0x0F;
+ entry->type = bType;
entry->next = *head;
*head = entry;
@@ -4006,7 +8365,7 @@ static int DecodeSubtree(byte* input, int sz, Base_entry** head, void* heap)
}
-static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert)
+static int DecodeNameConstraints(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
int length = 0;
@@ -4045,51 +8404,176 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert)
}
#endif /* IGNORE_NAME_CONSTRAINTS */
+#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || defined(OPENSSL_EXTRA)
-#ifdef WOLFSSL_SEP
- static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert)
+/* Decode ITU-T X.690 OID format to a string representation
+ * return string length */
+int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz)
+{
+ word32 val, inIdx = 0, outIdx = 0;
+ int w = 0;
+
+ if (out == NULL || in == NULL || outSz < 4 || inSz < 2)
+ return BAD_FUNC_ARG;
+
+ /* The first byte expands into b/40 dot b%40. */
+ val = in[inIdx++];
+
+ w = XSNPRINTF(out, outSz, "%u.%u", val / 40, val % 40);
+ if (w < 0)
+ goto exit;
+ outIdx += w;
+ val = 0;
+
+ while (inIdx < inSz && outIdx < outSz) {
+ /* extract the next OID digit from in to val */
+ /* first bit is used to set if value is coded on 1 or multiple bytes */
+ if (in[inIdx] & 0x80) {
+ val += in[inIdx] & 0x7F;
+ val *= 128;
+ }
+ else {
+ /* write val as text into out */
+ val += in[inIdx];
+ w = XSNPRINTF(out + outIdx, outSz - outIdx, ".%u", val);
+ if (w < 0)
+ goto exit;
+ outIdx += w;
+ val = 0;
+ }
+ inIdx++;
+ }
+ if (outIdx == outSz)
+ outIdx--;
+ out[outIdx] = 0;
+
+ w = (int)outIdx;
+
+exit:
+ return w;
+}
+#endif /* WOLFSSL_CERT_EXT && !WOLFSSL_SEP */
+
+#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_QT)
+ /* Reference: https://tools.ietf.org/html/rfc5280#section-4.2.1.4 */
+ static int DecodeCertPolicy(const byte* input, int sz, DecodedCert* cert)
{
word32 idx = 0;
- int length = 0;
+ word32 oldIdx;
+ int ret;
+ int total_length = 0, policy_length = 0, length = 0;
+ #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \
+ !defined(WOLFSSL_DUP_CERTPOL)
+ int i;
+ #endif
WOLFSSL_ENTER("DecodeCertPolicy");
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
+ /* Check if cert is null before dereferencing below */
+ if (cert == NULL)
+ return BAD_FUNC_ARG;
+ #endif
- /* Unwrap certificatePolicies */
- if (GetSequence(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tdeviceType isn't OID");
- return ASN_PARSE_E;
- }
+ #if defined(WOLFSSL_CERT_EXT)
+ cert->extCertPoliciesNb = 0;
+ #endif
- if (GetSequence(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tdeviceType isn't OID");
+ if (GetSequence(input, &idx, &total_length, sz) < 0) {
+ WOLFSSL_MSG("\tGet CertPolicy total seq failed");
return ASN_PARSE_E;
}
- if (input[idx++] != ASN_OBJECT_ID) {
- WOLFSSL_MSG("\tdeviceType isn't OID");
+ /* Validate total length */
+ if (total_length > (sz - (int)idx)) {
+ WOLFSSL_MSG("\tCertPolicy length mismatch");
return ASN_PARSE_E;
}
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tCouldn't read length of deviceType");
- return ASN_PARSE_E;
- }
+ /* Unwrap certificatePolicies */
+ do {
+ if (GetSequence(input, &idx, &policy_length, sz) < 0) {
+ WOLFSSL_MSG("\tGet CertPolicy seq failed");
+ return ASN_PARSE_E;
+ }
- if (length > 0) {
- cert->deviceType = (byte*)XMALLOC(length, cert->heap, 0);
- if (cert->deviceType == NULL) {
- WOLFSSL_MSG("\tCouldn't alloc memory for deviceType");
- return MEMORY_E;
+ oldIdx = idx;
+ ret = GetASNObjectId(input, &idx, &length, sz);
+ if (ret != 0)
+ return ret;
+ policy_length -= idx - oldIdx;
+
+ if (length > 0) {
+ /* Verify length won't overrun buffer */
+ if (length > (sz - (int)idx)) {
+ WOLFSSL_MSG("\tCertPolicy length exceeds input buffer");
+ return ASN_PARSE_E;
+ }
+
+ #if defined(WOLFSSL_SEP)
+ cert->deviceType = (byte*)XMALLOC(length, cert->heap,
+ DYNAMIC_TYPE_X509_EXT);
+ if (cert->deviceType == NULL) {
+ WOLFSSL_MSG("\tCouldn't alloc memory for deviceType");
+ return MEMORY_E;
+ }
+ cert->deviceTypeSz = length;
+ XMEMCPY(cert->deviceType, input + idx, length);
+ break;
+ #elif defined(WOLFSSL_CERT_EXT)
+ /* decode cert policy */
+ if (DecodePolicyOID(cert->extCertPolicies[
+ cert->extCertPoliciesNb], MAX_CERTPOL_SZ,
+ input + idx, length) <= 0) {
+ WOLFSSL_MSG("\tCouldn't decode CertPolicy");
+ return ASN_PARSE_E;
+ }
+ #ifndef WOLFSSL_DUP_CERTPOL
+ /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST
+ * NOT appear more than once in a certificate policies
+ * extension". This is a sanity check for duplicates.
+ * extCertPolicies should only have OID values, additional
+ * qualifiers need to be stored in a separate array. */
+ for (i = 0; i < cert->extCertPoliciesNb; i++) {
+ if (XMEMCMP(cert->extCertPolicies[i],
+ cert->extCertPolicies[cert->extCertPoliciesNb],
+ MAX_CERTPOL_SZ) == 0) {
+ WOLFSSL_MSG("Duplicate policy OIDs not allowed");
+ WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted");
+ return CERTPOLICIES_E;
+ }
+ }
+ #endif /* !WOLFSSL_DUP_CERTPOL */
+ cert->extCertPoliciesNb++;
+ #else
+ WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0);
+ return 0;
+ #endif
}
- cert->deviceTypeSz = length;
- XMEMCPY(cert->deviceType, input + idx, length);
- }
+ idx += policy_length;
+ } while((int)idx < total_length
+ #if defined(WOLFSSL_CERT_EXT)
+ && cert->extCertPoliciesNb < MAX_CERTPOL_NB
+ #endif
+ );
WOLFSSL_LEAVE("DecodeCertPolicy", 0);
return 0;
}
#endif /* WOLFSSL_SEP */
+/* Macro to check if bit is set, if not sets and return success.
+ Otherwise returns failure */
+/* Macro required here because bit-field operation */
+#ifndef WOLFSSL_NO_ASN_STRICT
+ #define VERIFY_AND_SET_OID(bit) \
+ if (bit == 0) \
+ bit = 1; \
+ else \
+ return ASN_OBJECT_ID_E;
+#else
+ /* With no strict defined, the verify is skipped */
+#define VERIFY_AND_SET_OID(bit) bit = 1;
+#endif
static int DecodeCertExtensions(DecodedCert* cert)
/*
@@ -4097,68 +8581,85 @@ static int DecodeCertExtensions(DecodedCert* cert)
* index. It is works starting with the recorded extensions pointer.
*/
{
+ int ret = 0;
word32 idx = 0;
int sz = cert->extensionsSz;
- byte* input = cert->extensions;
+ const byte* input = cert->extensions;
int length;
word32 oid;
byte critical = 0;
byte criticalFail = 0;
+ byte tag = 0;
WOLFSSL_ENTER("DecodeCertExtensions");
if (input == NULL || sz == 0)
return BAD_FUNC_ARG;
- if (input[idx++] != ASN_EXTENSIONS)
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
return ASN_PARSE_E;
+ }
- if (GetLength(input, &idx, &length, sz) < 0)
+ if (tag != ASN_EXTENSIONS) {
+ WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
return ASN_PARSE_E;
+ }
- if (GetSequence(input, &idx, &length, sz) < 0)
+ if (GetLength(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: invalid length");
return ASN_PARSE_E;
-
+ }
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
+ return ASN_PARSE_E;
+ }
+
while (idx < (word32)sz) {
+ word32 localIdx;
+
if (GetSequence(input, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
oid = 0;
- if (GetObjectId(input, &idx, &oid, sz) < 0) {
+ if ((ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz)) < 0) {
WOLFSSL_MSG("\tfail: OBJECT ID");
- return ASN_PARSE_E;
+ return ret;
}
/* check for critical flag */
critical = 0;
- if (input[idx] == ASN_BOOLEAN) {
- int boolLength = 0;
- idx++;
- if (GetLength(input, &idx, &boolLength, sz) < 0) {
- WOLFSSL_MSG("\tfail: critical boolean length");
- return ASN_PARSE_E;
- }
- if (input[idx++])
- critical = 1;
+ if ((idx + 1) > (word32)sz) {
+ WOLFSSL_MSG("\tfail: malformed buffer");
+ return BUFFER_E;
}
- /* process the extension based on the OID */
- if (input[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\tfail: should be an OCTET STRING");
- return ASN_PARSE_E;
+ localIdx = idx;
+ if (GetASNTag(input, &localIdx, &tag, sz) == 0) {
+ if (tag == ASN_BOOLEAN) {
+ ret = GetBoolean(input, &idx, sz);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: critical boolean");
+ return ret;
+ }
+
+ critical = (byte)ret;
+ }
}
- if (GetLength(input, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: extension data length");
- return ASN_PARSE_E;
+ /* process the extension based on the OID */
+ ret = GetOctetString(input, &idx, &length, sz);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tfail: bad OCTET STRING");
+ return ret;
}
switch (oid) {
case BASIC_CA_OID:
- #ifdef OPENSSL_EXTRA
- cert->extBasicConstSet = 1;
+ VERIFY_AND_SET_OID(cert->extBasicConstSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extBasicConstCrit = critical;
#endif
if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0)
@@ -4166,57 +8667,95 @@ static int DecodeCertExtensions(DecodedCert* cert)
break;
case CRL_DIST_OID:
+ VERIFY_AND_SET_OID(cert->extCRLdistSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extCRLdistCrit = critical;
+ #endif
if (DecodeCrlDist(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case AUTH_INFO_OID:
+ VERIFY_AND_SET_OID(cert->extAuthInfoSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
+ cert->extAuthInfoCrit = critical;
+ #endif
if (DecodeAuthInfo(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case ALT_NAMES_OID:
- #ifdef OPENSSL_EXTRA
- cert->extSubjAltNameSet = 1;
+ VERIFY_AND_SET_OID(cert->extSubjAltNameSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extSubjAltNameCrit = critical;
#endif
- if (DecodeAltNames(&input[idx], length, cert) < 0)
- return ASN_PARSE_E;
+ ret = DecodeAltNames(&input[idx], length, cert);
+ if (ret < 0)
+ return ret;
break;
case AUTH_KEY_OID:
- cert->extAuthKeyIdSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extAuthKeyIdSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extAuthKeyIdCrit = critical;
#endif
+ #ifndef WOLFSSL_ALLOW_CRIT_SKID
+ /* This check is added due to RFC 5280 section 4.2.1.1
+ * stating that conforming CA's must mark this extension
+ * as non-critical. When parsing extensions check that
+ * certificate was made in compliance with this. */
+ if (critical) {
+ WOLFSSL_MSG("Critical Auth Key ID is not allowed");
+ WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
+ return ASN_CRIT_EXT_E;
+ }
+ #endif
if (DecodeAuthKeyId(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case SUBJ_KEY_OID:
- cert->extSubjKeyIdSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extSubjKeyIdSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extSubjKeyIdCrit = critical;
#endif
+ #ifndef WOLFSSL_ALLOW_CRIT_SKID
+ /* This check is added due to RFC 5280 section 4.2.1.2
+ * stating that conforming CA's must mark this extension
+ * as non-critical. When parsing extensions check that
+ * certificate was made in compliance with this. */
+ if (critical) {
+ WOLFSSL_MSG("Critical Subject Key ID is not allowed");
+ WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted");
+ return ASN_CRIT_EXT_E;
+ }
+ #endif
+
if (DecodeSubjKeyId(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case CERT_POLICY_OID:
- WOLFSSL_MSG("Certificate Policy extension not supported yet.");
- #ifdef WOLFSSL_SEP
- #ifdef OPENSSL_EXTRA
- cert->extCertPolicySet = 1;
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
+ VERIFY_AND_SET_OID(cert->extCertPolicySet);
+ #if defined(OPENSSL_EXTRA) || \
+ defined(OPENSSL_EXTRA_X509_SMALL)
cert->extCertPolicyCrit = critical;
#endif
- if (DecodeCertPolicy(&input[idx], length, cert) < 0)
+ #endif
+ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) || \
+ defined(WOLFSSL_QT)
+ if (DecodeCertPolicy(&input[idx], length, cert) < 0) {
return ASN_PARSE_E;
+ }
+ #else
+ WOLFSSL_MSG("Certificate Policy extension not supported yet.");
#endif
break;
case KEY_USAGE_OID:
- cert->extKeyUsageSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extKeyUsageSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extKeyUsageCrit = critical;
#endif
if (DecodeKeyUsage(&input[idx], length, cert) < 0)
@@ -4224,8 +8763,8 @@ static int DecodeCertExtensions(DecodedCert* cert)
break;
case EXT_KEY_USAGE_OID:
- cert->extExtKeyUsageSet = 1;
- #ifdef OPENSSL_EXTRA
+ VERIFY_AND_SET_OID(cert->extExtKeyUsageSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extExtKeyUsageCrit = critical;
#endif
if (DecodeExtKeyUsage(&input[idx], length, cert) < 0)
@@ -4234,8 +8773,17 @@ static int DecodeCertExtensions(DecodedCert* cert)
#ifndef IGNORE_NAME_CONSTRAINTS
case NAME_CONS_OID:
- cert->extNameConstraintSet = 1;
- #ifdef OPENSSL_EXTRA
+ #ifndef WOLFSSL_NO_ASN_STRICT
+ /* Verify RFC 5280 Sec 4.2.1.10 rule:
+ "The name constraints extension,
+ which MUST be used only in a CA certificate" */
+ if (!cert->isCA) {
+ WOLFSSL_MSG("Name constraints allowed only for CA certs");
+ return ASN_NAME_INVALID_E;
+ }
+ #endif
+ VERIFY_AND_SET_OID(cert->extNameConstraintSet);
+ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
cert->extNameConstraintCrit = critical;
#endif
if (DecodeNameConstraints(&input[idx], length, cert) < 0)
@@ -4244,17 +8792,31 @@ static int DecodeCertExtensions(DecodedCert* cert)
#endif /* IGNORE_NAME_CONSTRAINTS */
case INHIBIT_ANY_OID:
+ VERIFY_AND_SET_OID(cert->inhibitAnyOidSet);
WOLFSSL_MSG("Inhibit anyPolicy extension not supported yet.");
break;
+ #ifndef IGNORE_NETSCAPE_CERT_TYPE
+ case NETSCAPE_CT_OID:
+ WOLFSSL_MSG("Netscape certificate type extension not supported "
+ "yet.");
+ if (CheckBitString(input, &idx, &length, idx + length, 0,
+ NULL) < 0) {
+ return ASN_PARSE_E;
+ }
+ break;
+ #endif
+
default:
+ #ifndef WOLFSSL_NO_ASN_STRICT
/* While it is a failure to not support critical extensions,
* still parse the certificate ignoring the unsupported
- * extention to allow caller to accept it with the verify
+ * extension to allow caller to accept it with the verify
* callback. */
if (critical)
criticalFail = 1;
- break;
+ #endif
+ break;
}
idx += length;
}
@@ -4262,7 +8824,6 @@ static int DecodeCertExtensions(DecodedCert* cert)
return criticalFail ? ASN_CRIT_EXT_E : 0;
}
-
int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
{
int ret;
@@ -4297,126 +8858,662 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm)
return ret;
}
-
/* from SSL proper, for locking can't do find here anymore */
#ifdef __cplusplus
extern "C" {
#endif
- WOLFSSL_LOCAL Signer* GetCA(void* signers, byte* hash);
+ Signer* GetCA(void* signers, byte* hash);
#ifndef NO_SKID
- WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash);
+ Signer* GetCAByName(void* signers, byte* hash);
#endif
#ifdef __cplusplus
- }
+ }
#endif
+#if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS)
+
+/* dummy functions, not using wolfSSL so don't need actual ones */
+Signer* GetCA(void* signers, byte* hash)
+{
+ (void)hash;
+
+ return (Signer*)signers;
+}
+
+#ifndef NO_SKID
+Signer* GetCAByName(void* signers, byte* hash)
+{
+ (void)hash;
+
+ return (Signer*)signers;
+}
+#endif /* NO_SKID */
+
+#endif /* WOLFCRYPT_ONLY || NO_CERTS */
+
+#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
+static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
+{
+ Signer* ca = NULL;
+ if (cert->extSubjKeyIdSet)
+ ca = GetCA(cm, cert->extSubjKeyId);
+ if (ca == NULL)
+ ca = GetCAByName(cm, cert->subjectHash);
+ if (ca) {
+ if ((ca->pubKeySize == cert->pubKeySize) &&
+ (XMEMCMP(ca->publicKey, cert->publicKey, ca->pubKeySize) == 0)) {
+ return ca;
+ }
+ }
+ return NULL;
+}
+#endif
+
+#if defined(WOLFSSL_SMALL_CERT_VERIFY) || defined(OPENSSL_EXTRA)
+/* Only quick step through the certificate to find fields that are then used
+ * in certificate signature verification.
+ * Must use the signature OID from the signed part of the certificate.
+ *
+ * This is only for minimizing dynamic memory usage during TLS certificate
+ * chain processing.
+ * Doesn't support:
+ * OCSP Only: alt lookup using subject and pub key w/o sig check
+ */
+static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
+ void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+{
+#ifndef WOLFSSL_SMALL_STACK
+ SignatureCtx sigCtx[1];
+#else
+ SignatureCtx* sigCtx;
+#endif
+ byte hash[KEYID_SIZE];
+ Signer* ca = NULL;
+ word32 idx = 0;
+ int len;
+ word32 tbsCertIdx = 0;
+ word32 sigIndex = 0;
+ word32 signatureOID = 0;
+ word32 oid = 0;
+ word32 issuerIdx = 0;
+ word32 issuerSz = 0;
+#ifndef NO_SKID
+ int extLen = 0;
+ word32 extIdx = 0;
+ word32 extEndIdx = 0;
+ int extAuthKeyIdSet = 0;
+#endif
+ int ret = 0;
+ word32 localIdx;
+ byte tag;
+
+
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ sigCtx = (SignatureCtx*)XMALLOC(sizeof(*sigCtx), heap, DYNAMIC_TYPE_SIGNATURE);
+ if (sigCtx == NULL)
+ return MEMORY_E;
+#endif
+ InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
+
+ /* Certificate SEQUENCE */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ tbsCertIdx = idx;
+
+ /* TBSCertificate SEQUENCE */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ sigIndex = len + idx;
+
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ if (ret == 0) {
+ /* version - optional */
+ localIdx = idx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+ idx++;
+ if (GetLength(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ idx += len;
+ }
+ }
+ }
+
+ if (ret == 0) {
+ /* serialNumber */
+ if (GetASNHeader(cert, ASN_INTEGER, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ /* signature */
+ if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ issuerIdx = idx;
+ /* issuer */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ issuerSz = len + idx - issuerIdx;
+ }
+#ifndef NO_SKID
+ if (ret == 0) {
+ idx += len;
+
+ /* validity */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ /* subject */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ /* subjectPublicKeyInfo */
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ idx += len;
+
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ if (ret == 0) {
+ /* issuerUniqueID - optional */
+ localIdx = idx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
+ idx++;
+ if (GetLength(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ idx += len;
+ }
+ }
+ }
+ if (ret == 0) {
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ if (ret == 0) {
+ /* subjectUniqueID - optional */
+ localIdx = idx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+ if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) {
+ idx++;
+ if (GetLength(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ idx += len;
+ }
+ }
+ }
+
+ if (ret == 0) {
+ if ((idx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ /* extensions - optional */
+ localIdx = idx;
+ if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) {
+ idx++;
+ if (GetLength(cert, &idx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ if (GetSequence(cert, &idx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ extEndIdx = idx + extLen;
+
+ /* Check each extension for the ones we want. */
+ while (ret == 0 && idx < extEndIdx) {
+ if (GetSequence(cert, &idx, &len, certSz) < 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ extIdx = idx;
+ if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
+ certSz) < 0) {
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ if ((extIdx + 1) > certSz)
+ ret = BUFFER_E;
+ }
+ }
+
+ if (ret == 0) {
+ localIdx = extIdx;
+ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+ tag == ASN_BOOLEAN) {
+ if (GetBoolean(cert, &extIdx, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ }
+ if (ret == 0) {
+ if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ switch (oid) {
+ case AUTH_KEY_OID:
+ if (GetSequence(cert, &extIdx, &extLen, certSz) < 0)
+ ret = ASN_PARSE_E;
+
+ if (ret == 0 && (extIdx + 1) >= certSz)
+ ret = BUFFER_E;
+
+ if (ret == 0 &&
+ GetASNTag(cert, &extIdx, &tag, certSz) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | 0)) {
+ if (GetLength(cert, &extIdx, &extLen, certSz) <= 0)
+ ret = ASN_PARSE_E;
+ if (ret == 0) {
+ extAuthKeyIdSet = 1;
+ if (extLen == KEYID_SIZE)
+ XMEMCPY(hash, cert + extIdx, extLen);
+ else {
+ ret = CalcHashId(cert + extIdx, extLen,
+ hash);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ idx += len;
+ }
+ }
+ }
+
+ if (ret == 0 && pubKey == NULL) {
+ if (extAuthKeyIdSet)
+ ca = GetCA(cm, hash);
+ if (ca == NULL) {
+ ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+ if (ret == 0)
+ ca = GetCAByName(cm, hash);
+ }
+ }
+#else
+ if (ret == 0 && pubKey == NULL) {
+ ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+ if (ret == 0)
+ ca = GetCA(cm, hash);
+ }
+#endif /* !NO_SKID */
+ if (ca == NULL && pubKey == NULL)
+ ret = ASN_NO_SIGNER_E;
+
+ if (ret == 0) {
+ idx = sigIndex;
+ /* signatureAlgorithm */
+ if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ if (oid != signatureOID)
+ ret = ASN_SIG_OID_E;
+ }
+ if (ret == 0) {
+ /* signatureValue */
+ if (CheckBitString(cert, &idx, &len, certSz, 1, NULL) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ if (pubKey != NULL) {
+ ret = ConfirmSignature(sigCtx, cert + tbsCertIdx,
+ sigIndex - tbsCertIdx,
+ pubKey, pubKeySz, pubKeyOID,
+ cert + idx, len, signatureOID, NULL);
+ }
+ else {
+ ret = ConfirmSignature(sigCtx, cert + tbsCertIdx,
+ sigIndex - tbsCertIdx,
+ ca->publicKey, ca->pubKeySize, ca->keyOID,
+ cert + idx, len, signatureOID, NULL);
+ }
+ if (ret != 0) {
+ WOLFSSL_MSG("Confirm signature failed");
+ }
+ }
+
+ FreeSignatureCtx(sigCtx);
+#ifdef WOLFSSL_SMALL_STACK
+ if (sigCtx != NULL)
+ XFREE(sigCtx, heap, DYNAMIC_TYPE_SIGNATURE);
+#endif
+ return ret;
+}
+
+#ifdef OPENSSL_EXTRA
+/* Call CheckCertSignature_ex using a public key buffer for verification
+ */
+int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap,
+ const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+{
+ return CheckCertSignature_ex(cert, certSz, heap, NULL,
+ pubKey, pubKeySz, pubKeyOID);
+}
+#endif /* OPENSSL_EXTRA */
+#ifdef WOLFSSL_SMALL_CERT_VERIFY
+/* Call CheckCertSignature_ex using a certificate manager (cm)
+ */
+int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm)
+{
+ return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0);
+}
+#endif /* WOLFSSL_SMALL_CERT_VERIFY */
+#endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */
int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
{
+ int ret = 0;
+ int checkPathLen = 0;
+ int decrementMaxPathLen = 0;
word32 confirmOID;
- int ret;
- int badDate = 0;
- int criticalExt = 0;
+#if defined(WOLFSSL_RENESAS_TSIP)
+ int idx = 0;
+#endif
+ byte* tsip_encRsaKeyIdx;
- if ((ret = DecodeToKey(cert, verify)) < 0) {
- if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
- badDate = ret;
- else
- return ret;
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
}
- WOLFSSL_MSG("Parsed Past Key");
+ if (cert->sigCtx.state == SIG_STATE_BEGIN) {
+ cert->badDate = 0;
+ cert->criticalExt = 0;
+ if ((ret = DecodeToKey(cert, verify)) < 0) {
+ if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)
+ cert->badDate = ret;
+ else
+ return ret;
+ }
+
+ WOLFSSL_MSG("Parsed Past Key");
- if (cert->srcIdx < cert->sigIndex) {
+ if (cert->srcIdx < cert->sigIndex) {
#ifndef ALLOW_V1_EXTENSIONS
if (cert->version < 2) {
- WOLFSSL_MSG(" v1 and v2 certs not allowed extensions");
+ WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions");
return ASN_VERSION_E;
}
#endif
- /* save extensions */
- cert->extensions = &cert->source[cert->srcIdx];
- cert->extensionsSz = cert->sigIndex - cert->srcIdx;
- cert->extensionsIdx = cert->srcIdx; /* for potential later use */
-
- if ((ret = DecodeCertExtensions(cert)) < 0) {
- if (ret == ASN_CRIT_EXT_E)
- criticalExt = ret;
- else
- return ret;
- }
- /* advance past extensions */
- cert->srcIdx = cert->sigIndex;
- }
+ /* save extensions */
+ cert->extensions = &cert->source[cert->srcIdx];
+ cert->extensionsSz = cert->sigIndex - cert->srcIdx;
+ cert->extensionsIdx = cert->srcIdx; /* for potential later use */
- if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
- cert->maxIdx)) < 0)
- return ret;
+ if ((ret = DecodeCertExtensions(cert)) < 0) {
+ if (ret == ASN_CRIT_EXT_E)
+ cert->criticalExt = ret;
+ else
+ return ret;
+ }
- if ((ret = GetSignature(cert)) < 0)
- return ret;
+ /* advance past extensions */
+ cert->srcIdx = cert->sigIndex;
+ }
+
+ if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
+ oidSigType, cert->maxIdx)) < 0)
+ return ret;
+
+ if ((ret = GetSignature(cert)) < 0)
+ return ret;
- if (confirmOID != cert->signatureOID)
- return ASN_SIG_OID_E;
+ if (confirmOID != cert->signatureOID)
+ return ASN_SIG_OID_E;
#ifndef NO_SKID
- if (cert->extSubjKeyIdSet == 0
- && cert->publicKey != NULL && cert->pubKeySize > 0) {
- #ifdef NO_SHA
- ret = wc_Sha256Hash(cert->publicKey, cert->pubKeySize,
+ if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL &&
+ cert->pubKeySize > 0) {
+ ret = CalcHashId(cert->publicKey, cert->pubKeySize,
cert->extSubjKeyId);
- #else
- ret = wc_ShaHash(cert->publicKey, cert->pubKeySize,
- cert->extSubjKeyId);
- #endif
if (ret != 0)
return ret;
}
- #endif
+ #endif /* !NO_SKID */
- if (verify && type != CA_TYPE) {
- Signer* ca = NULL;
- #ifndef NO_SKID
- if (cert->extAuthKeyIdSet)
- ca = GetCA(cm, cert->extAuthKeyId);
- if (ca == NULL)
- ca = GetCAByName(cm, cert->issuerHash);
- #else /* NO_SKID */
- ca = GetCA(cm, cert->issuerHash);
- #endif /* NO SKID */
- WOLFSSL_MSG("About to verify certificate signature");
-
- if (ca) {
-#ifdef HAVE_OCSP
- /* Need the ca's public key hash for OCSP */
- #ifdef NO_SHA
- ret = wc_Sha256Hash(ca->publicKey, ca->pubKeySize,
- cert->issuerKeyHash);
- #else /* NO_SHA */
- ret = wc_ShaHash(ca->publicKey, ca->pubKeySize,
- cert->issuerKeyHash);
- #endif /* NO_SHA */
- if (ret != 0)
- return ret;
-#endif /* HAVE_OCSP */
- /* try to confirm/verify signature */
- if (!ConfirmSignature(cert->source + cert->certBegin,
+ if (!cert->selfSigned || (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE)) {
+ cert->ca = NULL;
+ #ifndef NO_SKID
+ if (cert->extAuthKeyIdSet) {
+ cert->ca = GetCA(cm, cert->extAuthKeyId);
+ }
+ if (cert->ca == NULL && cert->extSubjKeyIdSet
+ && verify != VERIFY_OCSP) {
+ cert->ca = GetCA(cm, cert->extSubjKeyId);
+ }
+ if (cert->ca != NULL && XMEMCMP(cert->issuerHash,
+ cert->ca->subjectNameHash, KEYID_SIZE) != 0) {
+ cert->ca = NULL;
+ }
+ if (cert->ca == NULL) {
+ cert->ca = GetCAByName(cm, cert->issuerHash);
+ /* If AKID is available then this CA doesn't have the public
+ * key required */
+ if (cert->ca && cert->extAuthKeyIdSet) {
+ WOLFSSL_MSG("CA SKID doesn't match AKID");
+ cert->ca = NULL;
+ }
+ }
+
+ /* OCSP Only: alt lookup using subject and pub key w/o sig check */
+ #ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY
+ if (cert->ca == NULL && verify == VERIFY_OCSP) {
+ cert->ca = GetCABySubjectAndPubKey(cert, cm);
+ if (cert->ca) {
+ ret = 0; /* success */
+ goto exit_pcr;
+ }
+ }
+ #endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */
+ #else
+ cert->ca = GetCA(cm, cert->issuerHash);
+ #endif /* !NO_SKID */
+ }
+
+ if (cert->selfSigned) {
+ cert->maxPathLen = WOLFSSL_MAX_PATH_LEN;
+ } else {
+ /* RFC 5280 Section 4.2.1.9:
+ *
+ * load/receive check
+ *
+ * 1) Is CA boolean set?
+ * No - SKIP CHECK
+ * Yes - Check key usage
+ * 2) Is Key usage extension present?
+ * No - goto 3
+ * Yes - check keyCertSign assertion
+ * 2.a) Is keyCertSign asserted?
+ * No - goto 4
+ * Yes - goto 3
+ * 3) Is pathLen set?
+ * No - goto 4
+ * Yes - check pathLen against maxPathLen.
+ * 3.a) Is pathLen less than maxPathLen?
+ * No - goto 4
+ * Yes - set maxPathLen to pathLen and EXIT
+ * 4) Is maxPathLen > 0?
+ * Yes - Reduce by 1
+ * No - ERROR
+ */
+
+ if (cert->ca && cert->pathLengthSet) {
+ cert->maxPathLen = cert->pathLength;
+ if (cert->isCA) {
+ WOLFSSL_MSG("\tCA boolean set");
+ if (cert->extKeyUsageSet) {
+ WOLFSSL_MSG("\tExtension Key Usage Set");
+ if ((cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) != 0) {
+ checkPathLen = 1;
+ } else {
+ decrementMaxPathLen = 1;
+ }
+ } else {
+ checkPathLen = 1;
+ } /* !cert->ca check */
+ } /* cert is not a CA (assuming entity cert) */
+
+ if (checkPathLen && cert->pathLengthSet) {
+ if (cert->pathLength < cert->ca->maxPathLen) {
+ WOLFSSL_MSG("\tmaxPathLen status: set to pathLength");
+ cert->maxPathLen = cert->pathLength;
+ } else {
+ decrementMaxPathLen = 1;
+ }
+ }
+
+ if (decrementMaxPathLen && cert->ca->maxPathLen > 0) {
+ WOLFSSL_MSG("\tmaxPathLen status: reduce by 1");
+ cert->maxPathLen = cert->ca->maxPathLen - 1;
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ WOLFSSL_MSG("\tmaxPathLen status: OK");
+ }
+ } else if (decrementMaxPathLen && cert->ca->maxPathLen == 0) {
+ cert->maxPathLen = 0;
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0");
+ WOLFSSL_MSG("\tmaxPathLen status: ERROR");
+ return ASN_PATHLEN_INV_E;
+ }
+ }
+ } else if (cert->ca && cert->isCA) {
+ /* case where cert->pathLength extension is not set */
+ if (cert->ca->maxPathLen > 0) {
+ cert->maxPathLen = cert->ca->maxPathLen - 1;
+ } else {
+ cert->maxPathLen = 0;
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ WOLFSSL_MSG("\tNon-entity cert, maxPathLen is 0");
+ WOLFSSL_MSG("\tmaxPathLen status: ERROR");
+ return ASN_PATHLEN_INV_E;
+ }
+ }
+ }
+ #ifdef HAVE_OCSP
+ if (verify != NO_VERIFY && type != CA_TYPE &&
+ type != TRUSTED_PEER_TYPE) {
+ if (cert->ca) {
+ /* Need the CA's public key hash for OCSP */
+ XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
+ KEYID_SIZE);
+ }
+
+ }
+ #endif /* HAVE_OCSP */
+ }
+ }
+#if defined(WOLFSSL_RENESAS_TSIP)
+ /* prepare for TSIP TLS cert verification API use */
+ if (cert->keyOID == RSAk) {
+ /* to call TSIP API, it needs keys position info in bytes */
+ if ((ret = RsaPublicKeyDecodeRawIndex(cert->publicKey, (word32*)&idx,
+ cert->pubKeySize,
+ &cert->sigCtx.pubkey_n_start,
+ &cert->sigCtx.pubkey_n_len,
+ &cert->sigCtx.pubkey_e_start,
+ &cert->sigCtx.pubkey_e_len)) != 0) {
+ WOLFSSL_MSG("Decoding index from cert failed.");
+ return ret;
+ }
+ cert->sigCtx.certBegin = cert->certBegin;
+ }
+ /* check if we can use TSIP for cert verification */
+ /* if the ca is verified as tsip root ca. */
+ /* TSIP can only handle 2048 bits(256 byte) key. */
+ if (cert->ca && tsip_checkCA(cert->ca->cm_idx) != 0 &&
+ cert->sigCtx.pubkey_n_len == 256) {
+
+ /* assign memory to encrypted tsip Rsa key index */
+ if (!cert->tsip_encRsaKeyIdx)
+ cert->tsip_encRsaKeyIdx =
+ (byte*)XMALLOC(TSIP_TLS_ENCPUBKEY_SZ_BY_CERTVRFY,
+ cert->heap, DYNAMIC_TYPE_RSA);
+ if (cert->tsip_encRsaKeyIdx == NULL)
+ return MEMORY_E;
+ } else {
+ if (cert->ca) {
+ /* TSIP isn't usable */
+ if (tsip_checkCA(cert->ca->cm_idx) == 0)
+ WOLFSSL_MSG("TSIP isn't usable because the ca isn't verified "
+ "by TSIP.");
+ else if (cert->sigCtx.pubkey_n_len != 256)
+ WOLFSSL_MSG("TSIP isn't usable because the ca isn't signed by "
+ "RSA 2048.");
+ else
+ WOLFSSL_MSG("TSIP isn't usable");
+ }
+ cert->tsip_encRsaKeyIdx = NULL;
+ }
+
+ tsip_encRsaKeyIdx = cert->tsip_encRsaKeyIdx;
+#else
+ tsip_encRsaKeyIdx = NULL;
+#endif
+
+ if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) {
+ if (cert->ca) {
+ if (verify == VERIFY || verify == VERIFY_OCSP ||
+ verify == VERIFY_SKIP_DATE) {
+ /* try to confirm/verify signature */
+ if ((ret = ConfirmSignature(&cert->sigCtx,
+ cert->source + cert->certBegin,
cert->sigIndex - cert->certBegin,
- ca->publicKey, ca->pubKeySize, ca->keyOID,
- cert->signature, cert->sigLength, cert->signatureOID,
- cert->heap)) {
- WOLFSSL_MSG("Confirm signature failed");
- return ASN_SIG_CONFIRM_E;
+ cert->ca->publicKey, cert->ca->pubKeySize,
+ cert->ca->keyOID, cert->signature,
+ cert->sigLength, cert->signatureOID,
+ tsip_encRsaKeyIdx)) != 0) {
+ if (ret != 0 && ret != WC_PENDING_E) {
+ WOLFSSL_MSG("Confirm signature failed");
+ }
+ return ret;
+ }
}
-#ifndef IGNORE_NAME_CONSTRAINTS
- /* check that this cert's name is permitted by the signer's
- * name constraints */
- if (!ConfirmNameConstraints(ca, cert)) {
- WOLFSSL_MSG("Confirm name constraint failed");
- return ASN_NAME_INVALID_E;
+ #ifndef IGNORE_NAME_CONSTRAINTS
+ if (verify == VERIFY || verify == VERIFY_OCSP ||
+ verify == VERIFY_NAME || verify == VERIFY_SKIP_DATE) {
+ /* check that this cert's name is permitted by the signer's
+ * name constraints */
+ if (!ConfirmNameConstraints(cert->ca, cert)) {
+ WOLFSSL_MSG("Confirm name constraint failed");
+ return ASN_NAME_INVALID_E;
+ }
}
-#endif /* IGNORE_NAME_CONSTRAINTS */
+ #endif /* IGNORE_NAME_CONSTRAINTS */
}
else {
/* no signer */
@@ -4425,15 +9522,22 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
}
}
- if (badDate != 0)
- return badDate;
+#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
+exit_pcr:
+#endif
- if (criticalExt != 0)
- return criticalExt;
+ if (cert->badDate != 0) {
+ if (verify != VERIFY_SKIP_DATE) {
+ return cert->badDate;
+ }
+ WOLFSSL_MSG("Date error: Verify option is skipping");
+ }
- return 0;
-}
+ if (cert->criticalExt != 0)
+ return cert->criticalExt;
+ return ret;
+}
/* Create and init an new signer */
Signer* MakeSigner(void* heap)
@@ -4441,16 +9545,7 @@ Signer* MakeSigner(void* heap)
Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap,
DYNAMIC_TYPE_SIGNER);
if (signer) {
- signer->pubKeySize = 0;
- signer->keyOID = 0;
- signer->publicKey = NULL;
- signer->nameLen = 0;
- signer->name = NULL;
- #ifndef IGNORE_NAME_CONSTRAINTS
- signer->permittedNames = NULL;
- signer->excludedNames = NULL;
- #endif /* IGNORE_NAME_CONSTRAINTS */
- signer->next = NULL;
+ XMEMSET(signer, 0, sizeof(Signer));
}
(void)heap;
@@ -4462,13 +9557,16 @@ Signer* MakeSigner(void* heap)
void FreeSigner(Signer* signer, void* heap)
{
XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
- XFREE(signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- #ifndef IGNORE_NAME_CONSTRAINTS
- if (signer->permittedNames)
- FreeNameSubtrees(signer->permittedNames, heap);
- if (signer->excludedNames)
- FreeNameSubtrees(signer->excludedNames, heap);
- #endif
+ XFREE((void*)signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+#ifndef IGNORE_NAME_CONSTRAINTS
+ if (signer->permittedNames)
+ FreeNameSubtrees(signer->permittedNames, heap);
+ if (signer->excludedNames)
+ FreeNameSubtrees(signer->excludedNames, heap);
+#endif
+#ifdef WOLFSSL_SIGNER_DER_CERT
+ FreeDer(&signer->derCert);
+#endif
XFREE(signer, heap, DYNAMIC_TYPE_SIGNER);
(void)heap;
@@ -4491,14 +9589,59 @@ void FreeSignerTable(Signer** table, int rows, void* heap)
}
}
+#ifdef WOLFSSL_TRUST_PEER_CERT
+/* Free an individual trusted peer cert */
+void FreeTrustedPeer(TrustedPeerCert* tp, void* heap)
+{
+ if (tp == NULL) {
+ return;
+ }
+
+ if (tp->name) {
+ XFREE(tp->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
+ }
+
+ if (tp->sig) {
+ XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE);
+ }
+#ifndef IGNORE_NAME_CONSTRAINTS
+ if (tp->permittedNames)
+ FreeNameSubtrees(tp->permittedNames, heap);
+ if (tp->excludedNames)
+ FreeNameSubtrees(tp->excludedNames, heap);
+#endif
+ XFREE(tp, heap, DYNAMIC_TYPE_CERT);
+
+ (void)heap;
+}
+
+/* Free the whole Trusted Peer linked list */
+void FreeTrustedPeerTable(TrustedPeerCert** table, int rows, void* heap)
+{
+ int i;
+
+ for (i = 0; i < rows; i++) {
+ TrustedPeerCert* tp = table[i];
+ while (tp) {
+ TrustedPeerCert* next = tp->next;
+ FreeTrustedPeer(tp, heap);
+ tp = next;
+ }
+ table[i] = NULL;
+ }
+}
+#endif /* WOLFSSL_TRUST_PEER_CERT */
-WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header)
+int SetMyVersion(word32 version, byte* output, int header)
{
int i = 0;
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
if (header) {
output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
- output[i++] = ASN_BIT_STRING;
+ output[i++] = 3;
}
output[i++] = ASN_INTEGER;
output[i++] = 0x01;
@@ -4507,65 +9650,558 @@ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header)
return i;
}
+int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
+ word32 outputSz, int maxSnSz)
+{
+ int i;
+ int snSzInt = (int)snSz;
+
+ if (sn == NULL || output == NULL || snSzInt < 0)
+ return BAD_FUNC_ARG;
+
+ /* remove leading zeros */
+ while (snSzInt > 0 && sn[0] == 0) {
+ snSzInt--;
+ sn++;
+ }
+ /* RFC 5280 - 4.1.2.2:
+ * Serial numbers must be a positive value (and not zero) */
+ if (snSzInt == 0)
+ return BAD_FUNC_ARG;
+
+ if (sn[0] & 0x80)
+ maxSnSz--;
+ /* truncate if input is too long */
+ if (snSzInt > maxSnSz)
+ snSzInt = maxSnSz;
+
+ i = SetASNInt(snSzInt, sn[0], NULL);
+ /* truncate if input is too long */
+ if (snSzInt > (int)outputSz - i)
+ snSzInt = (int)outputSz - i;
+ /* sanity check number of bytes to copy */
+ if (snSzInt <= 0) {
+ return BUFFER_E;
+ }
+
+ /* write out ASN.1 Integer */
+ (void)SetASNInt(snSzInt, sn[0], output);
+ XMEMCPY(output + i, sn, snSzInt);
-WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output)
+ /* compute final length */
+ i += snSzInt;
+
+ return i;
+}
+
+#endif /* !NO_CERTS */
+
+int GetSerialNumber(const byte* input, word32* inOutIdx,
+ byte* serial, int* serialSz, word32 maxIdx)
{
int result = 0;
+ int ret;
+
+ WOLFSSL_ENTER("GetSerialNumber");
+
+ if (serial == NULL || input == NULL || serialSz == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* First byte is ASN type */
+ if ((*inOutIdx+1) > maxIdx) {
+ WOLFSSL_MSG("Bad idx first");
+ return BUFFER_E;
+ }
+
+ ret = GetASNInt(input, inOutIdx, serialSz, maxIdx);
+ if (ret != 0)
+ return ret;
+
+ if (*serialSz > EXTERNAL_SERIAL_SIZE) {
+ WOLFSSL_MSG("Serial size bad");
+ return ASN_PARSE_E;
+ }
+
+ /* return serial */
+ XMEMCPY(serial, &input[*inOutIdx], *serialSz);
+ *inOutIdx += *serialSz;
+
+ return result;
+}
- WOLFSSL_ENTER("SetSerialNumber");
+#ifndef NO_CERTS
- if (snSz <= EXTERNAL_SERIAL_SIZE) {
- output[0] = ASN_INTEGER;
- /* The serial number is always positive. When encoding the
- * INTEGER, if the MSB is 1, add a padding zero to keep the
- * number positive. */
- if (sn[0] & 0x80) {
- output[1] = (byte)snSz + 1;
- output[2] = 0;
- XMEMCPY(&output[3], sn, snSz);
- result = snSz + 3;
+int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
+{
+ int ret = BAD_FUNC_ARG;
+ if (pDer) {
+ int dynType = 0;
+ DerBuffer* der;
+
+ /* Determine dynamic type */
+ switch (type) {
+ case CA_TYPE: dynType = DYNAMIC_TYPE_CA; break;
+ case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break;
+ case CRL_TYPE: dynType = DYNAMIC_TYPE_CRL; break;
+ case DSA_TYPE: dynType = DYNAMIC_TYPE_DSA; break;
+ case ECC_TYPE: dynType = DYNAMIC_TYPE_ECC; break;
+ case RSA_TYPE: dynType = DYNAMIC_TYPE_RSA; break;
+ default: dynType = DYNAMIC_TYPE_KEY; break;
}
- else {
- output[1] = (byte)snSz;
- XMEMCPY(&output[2], sn, snSz);
- result = snSz + 2;
+
+ /* Setup new buffer */
+ *pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType);
+ if (*pDer == NULL) {
+ return MEMORY_E;
}
+ XMEMSET(*pDer, 0, sizeof(DerBuffer) + length);
+
+ der = *pDer;
+ der->type = type;
+ der->dynType = dynType; /* Cache this for FreeDer */
+ der->heap = heap;
+ der->buffer = (byte*)der + sizeof(DerBuffer);
+ der->length = length;
+ ret = 0; /* Success */
}
- return result;
+ return ret;
}
+void FreeDer(DerBuffer** pDer)
+{
+ if (pDer && *pDer)
+ {
+ DerBuffer* der = (DerBuffer*)*pDer;
+ /* ForceZero private keys */
+ if (der->type == PRIVATEKEY_TYPE) {
+ ForceZero(der->buffer, der->length);
+ }
+ der->buffer = NULL;
+ der->length = 0;
+ XFREE(der, der->heap, der->dynType);
+ *pDer = NULL;
+ }
+}
-#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)
+int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap)
+{
+ return AllocDer(pDer, length, type, heap);
+}
+void wc_FreeDer(DerBuffer** pDer)
+{
+ FreeDer(pDer);
+}
+
+
+#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
+
+/* Max X509 header length indicates the max length + 2 ('\n', '\0') */
+#define MAX_X509_HEADER_SZ (37 + 2)
+
+wcchar BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
+wcchar END_CERT = "-----END CERTIFICATE-----";
+#ifdef WOLFSSL_CERT_REQ
+ wcchar BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----";
+ wcchar END_CERT_REQ = "-----END CERTIFICATE REQUEST-----";
+#endif
+#ifndef NO_DH
+ wcchar BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----";
+ wcchar END_DH_PARAM = "-----END DH PARAMETERS-----";
+#endif
+#ifndef NO_DSA
+ wcchar BEGIN_DSA_PARAM = "-----BEGIN DSA PARAMETERS-----";
+ wcchar END_DSA_PARAM = "-----END DSA PARAMETERS-----";
+#endif
+wcchar BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
+wcchar END_X509_CRL = "-----END X509 CRL-----";
+wcchar BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----";
+wcchar END_RSA_PRIV = "-----END RSA PRIVATE KEY-----";
+wcchar BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----";
+wcchar END_PRIV_KEY = "-----END PRIVATE KEY-----";
+wcchar BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+wcchar END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----";
+#ifdef HAVE_ECC
+ wcchar BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----";
+ wcchar END_EC_PRIV = "-----END EC PRIVATE KEY-----";
+#endif
+#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+ !defined(NO_DSA)
+ wcchar BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----";
+ wcchar END_DSA_PRIV = "-----END DSA PRIVATE KEY-----";
+#endif
+#ifdef OPENSSL_EXTRA
+ const char BEGIN_PRIV_KEY_PREFIX[] = "-----BEGIN";
+ const char PRIV_KEY_SUFFIX[] = "PRIVATE KEY-----";
+ const char END_PRIV_KEY_PREFIX[] = "-----END";
+#endif
+wcchar BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----";
+wcchar END_PUB_KEY = "-----END PUBLIC KEY-----";
+#if defined(HAVE_ED25519) || defined(HAVE_ED448)
+ wcchar BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----";
+ wcchar END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----";
+#endif
+#ifdef HAVE_CRL
+ const char *const BEGIN_CRL = "-----BEGIN X509 CRL-----";
+ wcchar END_CRL = "-----END X509 CRL-----";
+#endif
+
+
+static WC_INLINE char* SkipEndOfLineChars(char* line, const char* endOfLine)
+{
+ /* eat end of line characters */
+ while (line < endOfLine &&
+ (line[0] == '\r' || line[0] == '\n')) {
+ line++;
+ }
+ return line;
+}
+
+int wc_PemGetHeaderFooter(int type, const char** header, const char** footer)
+{
+ int ret = BAD_FUNC_ARG;
+
+ switch (type) {
+ case CA_TYPE: /* same as below */
+ case TRUSTED_PEER_TYPE:
+ case CERT_TYPE:
+ if (header) *header = BEGIN_CERT;
+ if (footer) *footer = END_CERT;
+ ret = 0;
+ break;
+
+ case CRL_TYPE:
+ if (header) *header = BEGIN_X509_CRL;
+ if (footer) *footer = END_X509_CRL;
+ ret = 0;
+ break;
+ #ifndef NO_DH
+ case DH_PARAM_TYPE:
+ if (header) *header = BEGIN_DH_PARAM;
+ if (footer) *footer = END_DH_PARAM;
+ ret = 0;
+ break;
+ #endif
+ #ifndef NO_DSA
+ case DSA_PARAM_TYPE:
+ if (header) *header = BEGIN_DSA_PARAM;
+ if (footer) *footer = END_DSA_PARAM;
+ ret = 0;
+ break;
+ #endif
+ #ifdef WOLFSSL_CERT_REQ
+ case CERTREQ_TYPE:
+ if (header) *header = BEGIN_CERT_REQ;
+ if (footer) *footer = END_CERT_REQ;
+ ret = 0;
+ break;
+ #endif
+ #ifndef NO_DSA
+ case DSA_TYPE:
+ case DSA_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_DSA_PRIV;
+ if (footer) *footer = END_DSA_PRIV;
+ ret = 0;
+ break;
+ #endif
+ #ifdef HAVE_ECC
+ case ECC_TYPE:
+ case ECC_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_EC_PRIV;
+ if (footer) *footer = END_EC_PRIV;
+ ret = 0;
+ break;
+ #endif
+ case RSA_TYPE:
+ case PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_RSA_PRIV;
+ if (footer) *footer = END_RSA_PRIV;
+ ret = 0;
+ break;
+ #ifdef HAVE_ED25519
+ case ED25519_TYPE:
+ #endif
+ #ifdef HAVE_ED448
+ case ED448_TYPE:
+ #endif
+ #if defined(HAVE_ED25519) || defined(HAVE_ED448)
+ case EDDSA_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_EDDSA_PRIV;
+ if (footer) *footer = END_EDDSA_PRIV;
+ ret = 0;
+ break;
+ #endif
+ case PUBLICKEY_TYPE:
+ case ECC_PUBLICKEY_TYPE:
+ if (header) *header = BEGIN_PUB_KEY;
+ if (footer) *footer = END_PUB_KEY;
+ ret = 0;
+ break;
+ #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+ case DH_PRIVATEKEY_TYPE:
+ #endif
+ case PKCS8_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_PRIV_KEY;
+ if (footer) *footer = END_PRIV_KEY;
+ ret = 0;
+ break;
+ case PKCS8_ENC_PRIVATEKEY_TYPE:
+ if (header) *header = BEGIN_ENC_PRIV_KEY;
+ if (footer) *footer = END_ENC_PRIV_KEY;
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+
+static wcchar kProcTypeHeader = "Proc-Type";
+static wcchar kDecInfoHeader = "DEK-Info";
+
+#ifdef WOLFSSL_PEM_TO_DER
+#ifndef NO_DES3
+ static wcchar kEncTypeDes = "DES-CBC";
+ static wcchar kEncTypeDes3 = "DES-EDE3-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
+ static wcchar kEncTypeAesCbc128 = "AES-128-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
+ static wcchar kEncTypeAesCbc192 = "AES-192-CBC";
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
+ static wcchar kEncTypeAesCbc256 = "AES-256-CBC";
+#endif
+
+int wc_EncryptedInfoGet(EncryptedInfo* info, const char* cipherInfo)
+{
+ int ret = 0;
+
+ if (info == NULL || cipherInfo == NULL)
+ return BAD_FUNC_ARG;
+
+ /* determine cipher information */
+#ifndef NO_DES3
+ if (XSTRNCMP(cipherInfo, kEncTypeDes, XSTRLEN(kEncTypeDes)) == 0) {
+ info->cipherType = WC_CIPHER_DES;
+ info->keySz = DES_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = DES_IV_SIZE;
+ }
+ else if (XSTRNCMP(cipherInfo, kEncTypeDes3, XSTRLEN(kEncTypeDes3)) == 0) {
+ info->cipherType = WC_CIPHER_DES3;
+ info->keySz = DES3_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = DES_IV_SIZE;
+ }
+ else
+#endif /* !NO_DES3 */
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128)
+ if (XSTRNCMP(cipherInfo, kEncTypeAesCbc128, XSTRLEN(kEncTypeAesCbc128)) == 0) {
+ info->cipherType = WC_CIPHER_AES_CBC;
+ info->keySz = AES_128_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = AES_IV_SIZE;
+ }
+ else
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192)
+ if (XSTRNCMP(cipherInfo, kEncTypeAesCbc192, XSTRLEN(kEncTypeAesCbc192)) == 0) {
+ info->cipherType = WC_CIPHER_AES_CBC;
+ info->keySz = AES_192_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = AES_IV_SIZE;
+ }
+ else
+#endif
+#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256)
+ if (XSTRNCMP(cipherInfo, kEncTypeAesCbc256, XSTRLEN(kEncTypeAesCbc256)) == 0) {
+ info->cipherType = WC_CIPHER_AES_CBC;
+ info->keySz = AES_256_KEY_SIZE;
+ if (info->ivSz == 0) info->ivSz = AES_IV_SIZE;
+ }
+ else
+#endif
+ {
+ ret = NOT_COMPILED_IN;
+ }
+ return ret;
+}
+
+int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, size_t bufSz)
+{
+ int err = 0;
+ char* bufferStart;
+ char* bufferEnd;
+ char* line;
+ word32 lineSz;
+ char* finish;
+ word32 finishSz;
+ char* start = NULL;
+ word32 startSz;
+ char* newline = NULL;
+
+ if (info == NULL || pBuffer == NULL || bufSz == 0)
+ return BAD_FUNC_ARG;
+
+ bufferStart = *pBuffer;
+ bufferEnd = bufferStart + bufSz;
+
+ /* find encrypted info marker */
+ line = XSTRNSTR(bufferStart, kProcTypeHeader,
+ min((word32)bufSz, PEM_LINE_LEN));
+ if (line != NULL) {
+ if (line >= bufferEnd) {
+ return BUFFER_E;
+ }
+
+ lineSz = (word32)(bufferEnd - line);
+
+ /* find DEC-Info marker */
+ start = XSTRNSTR(line, kDecInfoHeader, min(lineSz, PEM_LINE_LEN));
+
+ if (start == NULL)
+ return BUFFER_E;
+
+ /* skip dec-info and ": " */
+ start += XSTRLEN(kDecInfoHeader);
+ if (start >= bufferEnd)
+ return BUFFER_E;
+
+ if (start[0] == ':') {
+ start++;
+ if (start >= bufferEnd)
+ return BUFFER_E;
+ }
+ if (start[0] == ' ')
+ start++;
+
+ startSz = (word32)(bufferEnd - start);
+ finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN));
+
+ if ((start != NULL) && (finish != NULL) && (start < finish)) {
+ if (finish >= bufferEnd) {
+ return BUFFER_E;
+ }
+
+ finishSz = (word32)(bufferEnd - finish);
+ newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN));
+
+ /* get cipher name */
+ if (NAME_SZ < (finish - start)) /* buffer size of info->name */
+ return BUFFER_E;
+ if (XMEMCPY(info->name, start, finish - start) == NULL)
+ return BUFFER_E;
+ info->name[finish - start] = '\0'; /* null term */
+
+ /* populate info */
+ err = wc_EncryptedInfoGet(info, info->name);
+ if (err != 0)
+ return err;
+
+ /* get IV */
+ if (finishSz < info->ivSz + 1)
+ return BUFFER_E;
+
+ if (newline == NULL) {
+ newline = XSTRNSTR(finish, "\n", min(finishSz,
+ PEM_LINE_LEN));
+ }
+ if ((newline != NULL) && (newline > finish)) {
+ finish++;
+ info->ivSz = (word32)(newline - finish);
+ if (info->ivSz > IV_SZ)
+ return BUFFER_E;
+ if (XMEMCPY(info->iv, finish, info->ivSz) == NULL)
+ return BUFFER_E;
+ info->set = 1;
+ }
+ else
+ return BUFFER_E;
+ }
+ else
+ return BUFFER_E;
+
+ /* eat end of line characters */
+ newline = SkipEndOfLineChars(newline, bufferEnd);
+
+ /* return new headerEnd */
+
+ *pBuffer = newline;
+ }
+
+ return err;
+}
+#endif /* WOLFSSL_PEM_TO_DER */
+
+#ifdef WOLFSSL_DER_TO_PEM
+static int wc_EncryptedInfoAppend(char* dest, int destSz, char* cipherInfo)
+{
+ if (cipherInfo != NULL) {
+ int cipherInfoStrLen = (int)XSTRLEN((char*)cipherInfo);
+
+ if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3))
+ cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3);
+
+ if (destSz - (int)XSTRLEN(dest) >= cipherInfoStrLen + (9+14+8+2+2+1)) {
+ /* strncat's src length needs to include the NULL */
+ XSTRNCAT(dest, kProcTypeHeader, 10);
+ XSTRNCAT(dest, ": 4,ENCRYPTED\n", 15);
+ XSTRNCAT(dest, kDecInfoHeader, 9);
+ XSTRNCAT(dest, ": ", 3);
+ XSTRNCAT(dest, cipherInfo, destSz - (int)XSTRLEN(dest) - 1);
+ XSTRNCAT(dest, "\n\n", 4);
+ }
+ }
+ return 0;
+}
+#endif /* WOLFSSL_DER_TO_PEM */
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+#ifdef WOLFSSL_DER_TO_PEM
+
+/* Used for compatibility API */
+int wc_DerToPem(const byte* der, word32 derSz,
+ byte* output, word32 outSz, int type)
+{
+ return wc_DerToPemEx(der, derSz, output, outSz, NULL, type);
+}
/* convert der buffer to pem into output, can't do inplace, der and output
need to be different */
-int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
- int type)
+int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz,
+ byte *cipher_info, int type)
{
+ const char* headerStr = NULL;
+ const char* footerStr = NULL;
#ifdef WOLFSSL_SMALL_STACK
char* header = NULL;
char* footer = NULL;
#else
- char header[80];
- char footer[80];
+ char header[MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE];
+ char footer[MAX_X509_HEADER_SZ];
#endif
-
- int headerLen = 80;
- int footerLen = 80;
+ int headerLen = MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE;
+ int footerLen = MAX_X509_HEADER_SZ;
int i;
int err;
int outLen; /* return length or error */
+ (void)cipher_info;
+
if (der == output) /* no in place conversion */
return BAD_FUNC_ARG;
+ err = wc_PemGetHeaderFooter(type, &headerStr, &footerStr);
+ if (err != 0)
+ return err;
+
#ifdef WOLFSSL_SMALL_STACK
header = (char*)XMALLOC(headerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (header == NULL)
return MEMORY_E;
-
+
footer = (char*)XMALLOC(footerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (footer == NULL) {
XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -4573,39 +10209,44 @@ int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
}
#endif
- if (type == CERT_TYPE) {
- XSTRNCPY(header, "-----BEGIN CERTIFICATE-----\n", headerLen);
- XSTRNCPY(footer, "-----END CERTIFICATE-----\n", footerLen);
- }
- else if (type == PRIVATEKEY_TYPE) {
- XSTRNCPY(header, "-----BEGIN RSA PRIVATE KEY-----\n", headerLen);
- XSTRNCPY(footer, "-----END RSA PRIVATE KEY-----\n", footerLen);
- }
- #ifdef HAVE_ECC
- else if (type == ECC_PRIVATEKEY_TYPE) {
- XSTRNCPY(header, "-----BEGIN EC PRIVATE KEY-----\n", headerLen);
- XSTRNCPY(footer, "-----END EC PRIVATE KEY-----\n", footerLen);
- }
+ /* build header and footer based on type */
+ XSTRNCPY(header, headerStr, headerLen - 1);
+ header[headerLen - 2] = 0;
+ XSTRNCPY(footer, footerStr, footerLen - 1);
+ footer[footerLen - 2] = 0;
+
+ /* add new line to end */
+ XSTRNCAT(header, "\n", 2);
+ XSTRNCAT(footer, "\n", 2);
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+ err = wc_EncryptedInfoAppend(header, headerLen, (char*)cipher_info);
+ if (err != 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- #ifdef WOLFSSL_CERT_REQ
- else if (type == CERTREQ_TYPE)
- {
- XSTRNCPY(header,
- "-----BEGIN CERTIFICATE REQUEST-----\n", headerLen);
- XSTRNCPY(footer, "-----END CERTIFICATE REQUEST-----\n", footerLen);
+ return err;
}
- #endif
- else {
+#endif
+
+ headerLen = (int)XSTRLEN(header);
+ footerLen = (int)XSTRLEN(footer);
+
+ /* if null output and 0 size passed in then return size needed */
+ if (!output && outSz == 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return BAD_FUNC_ARG;
+ outLen = 0;
+ if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen))
+ != LENGTH_ONLY_E) {
+ return err;
+ }
+ return headerLen + footerLen + outLen;
}
- headerLen = (int)XSTRLEN(header);
- footerLen = (int)XSTRLEN(footer);
-
if (!der || !output) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -4657,12 +10298,846 @@ int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outSz,
return outLen + headerLen + footerLen;
}
+#endif /* WOLFSSL_DER_TO_PEM */
+
+#ifdef WOLFSSL_PEM_TO_DER
+
+/* Remove PEM header/footer, convert to ASN1, store any encrypted data
+ info->consumed tracks of PEM bytes consumed in case multiple parts */
+int PemToDer(const unsigned char* buff, long longSz, int type,
+ DerBuffer** pDer, void* heap, EncryptedInfo* info, int* keyFormat)
+{
+ const char* header = NULL;
+ const char* footer = NULL;
+ char* headerEnd;
+ char* footerEnd;
+ char* consumedEnd;
+ char* bufferEnd = (char*)(buff + longSz);
+ long neededSz;
+ int ret = 0;
+ int sz = (int)longSz;
+ int encrypted_key = 0;
+ DerBuffer* der;
+#if defined(HAVE_PKCS8) || defined(WOLFSSL_ENCRYPTED_KEYS)
+ word32 algId = 0;
+ #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_WOLFSSL_SKIP_TRAILING_PAD)
+ int padVal = 0;
+ #endif
+#endif
+#ifdef OPENSSL_EXTRA
+ char beginBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */
+ char endBuf[PEM_LINE_LEN + 1]; /* add 1 for null terminator */
+#endif
+
+ WOLFSSL_ENTER("PemToDer");
+
+ /* get PEM header and footer based on type */
+ ret = wc_PemGetHeaderFooter(type, &header, &footer);
+ if (ret != 0)
+ return ret;
+
+ /* map header if not found for type */
+ for (;;) {
+ headerEnd = XSTRNSTR((char*)buff, header, sz);
+
+ if (headerEnd) {
+ break;
+ } else
+ if (type == PRIVATEKEY_TYPE) {
+ if (header == BEGIN_RSA_PRIV) {
+ header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY;
+ } else
+ if (header == BEGIN_PRIV_KEY) {
+ header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY;
+ } else
+ #ifdef HAVE_ECC
+ if (header == BEGIN_ENC_PRIV_KEY) {
+ header = BEGIN_EC_PRIV; footer = END_EC_PRIV;
+ } else
+ if (header == BEGIN_EC_PRIV) {
+ header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV;
+ } else
+ #endif
+ #if defined(HAVE_ED25519) || defined(HAVE_ED448)
+ #ifdef HAVE_ECC
+ if (header == BEGIN_DSA_PRIV)
+ #else
+ if (header == BEGIN_ENC_PRIV_KEY)
+ #endif
+ {
+ header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV;
+ } else
+ #endif
+ {
+ break;
+ }
+ } else
+#ifdef HAVE_CRL
+ if ((type == CRL_TYPE) && (header != BEGIN_CRL)) {
+ header = BEGIN_CRL; footer = END_CRL;
+ } else
+#endif
+ {
+ break;
+ }
+ }
+
+ if (!headerEnd) {
+#ifdef OPENSSL_EXTRA
+ char* beginEnd;
+ int endLen;
+ /* see if there is a -----BEGIN * PRIVATE KEY----- header */
+ headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz);
+ if (headerEnd) {
+ beginEnd = headerEnd + XSTR_SIZEOF(PRIV_KEY_SUFFIX);
+ /* back up to BEGIN_PRIV_KEY_PREFIX */
+ headerEnd -= XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX);
+ while (headerEnd > (char*)buff &&
+ XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+ XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0) {
+ headerEnd--;
+ }
+ if (headerEnd <= (char*)buff ||
+ XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+ XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 ||
+ beginEnd - headerEnd > PEM_LINE_LEN) {
+ WOLFSSL_MSG("Couldn't find PEM header");
+ return ASN_NO_PEM_HEADER;
+ }
+ /* headerEnd now points to beginning of header */
+ XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd);
+ beginBuf[beginEnd - headerEnd] = '\0';
+ /* look for matching footer */
+ footer = XSTRNSTR(beginEnd,
+ beginBuf + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX),
+ (unsigned int)((char*)buff + sz - beginEnd));
+ if (!footer) {
+ WOLFSSL_MSG("Couldn't find PEM footer");
+ return ASN_NO_PEM_HEADER;
+ }
+ footer -= XSTR_SIZEOF(END_PRIV_KEY_PREFIX);
+ endLen = (unsigned int)(beginEnd - headerEnd -
+ (XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) -
+ XSTR_SIZEOF(END_PRIV_KEY_PREFIX)));
+ XMEMCPY(endBuf, footer, endLen);
+ endBuf[endLen] = '\0';
+
+ header = beginBuf;
+ footer = endBuf;
+ headerEnd = beginEnd;
+ } else {
+ WOLFSSL_MSG("Couldn't find PEM header");
+ return ASN_NO_PEM_HEADER;
+ }
+#else
+ WOLFSSL_MSG("Couldn't find PEM header");
+ return ASN_NO_PEM_HEADER;
+#endif
+ } else {
+ headerEnd += XSTRLEN(header);
+ }
+
+ /* eat end of line characters */
+ headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd);
+
+ if (type == PRIVATEKEY_TYPE) {
+ /* keyFormat is Key_Sum enum */
+ if (keyFormat) {
+ #ifdef HAVE_ECC
+ if (header == BEGIN_EC_PRIV)
+ *keyFormat = ECDSAk;
+ #endif
+ #if !defined(NO_DSA)
+ if (header == BEGIN_DSA_PRIV)
+ *keyFormat = DSAk;
+ #endif
+ }
+ }
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+ if (info) {
+ ret = wc_EncryptedInfoParse(info, &headerEnd, bufferEnd - headerEnd);
+ if (ret < 0)
+ return ret;
+ if (info->set)
+ encrypted_key = 1;
+ }
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+ /* find footer */
+ footerEnd = XSTRNSTR(headerEnd, footer, (unsigned int)((char*)buff + sz - headerEnd));
+ if (!footerEnd) {
+ if (info)
+ info->consumed = longSz; /* No more certs if no footer */
+ return BUFFER_E;
+ }
+
+ consumedEnd = footerEnd + XSTRLEN(footer);
+
+ if (consumedEnd < bufferEnd) { /* handle no end of line on last line */
+ /* eat end of line characters */
+ consumedEnd = SkipEndOfLineChars(consumedEnd, bufferEnd);
+ /* skip possible null term */
+ if (consumedEnd < bufferEnd && consumedEnd[0] == '\0')
+ consumedEnd++;
+ }
+
+ if (info)
+ info->consumed = (long)(consumedEnd - (char*)buff);
+
+ /* set up der buffer */
+ neededSz = (long)(footerEnd - headerEnd);
+ if (neededSz > sz || neededSz <= 0)
+ return BUFFER_E;
+
+ ret = AllocDer(pDer, (word32)neededSz, type, heap);
+ if (ret < 0) {
+ return ret;
+ }
+ der = *pDer;
+
+ if (Base64_Decode((byte*)headerEnd, (word32)neededSz,
+ der->buffer, &der->length) < 0)
+ return BUFFER_E;
+
+ if ((header == BEGIN_PRIV_KEY
+#ifdef OPENSSL_EXTRA
+ || header == beginBuf
+#endif
+#ifdef HAVE_ECC
+ || header == BEGIN_EC_PRIV
+#endif
+ ) && !encrypted_key)
+ {
+ #ifdef HAVE_PKCS8
+ /* pkcs8 key, convert and adjust length */
+ if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) {
+ der->length = ret;
+ if (keyFormat) {
+ *keyFormat = algId;
+ }
+ }
+ else {
+ /* ignore failure here and assume key is not pkcs8 wrapped */
+ }
+ #endif
+
+ return 0;
+ }
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+ if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) {
+ int passwordSz = NAME_SZ;
+ #ifdef WOLFSSL_SMALL_STACK
+ char* password = NULL;
+ #else
+ char password[NAME_SZ];
+ #endif
+
+ if (!info || !info->passwd_cb) {
+ WOLFSSL_MSG("No password callback set");
+ return NO_PASSWORD;
+ }
+
+ #ifdef WOLFSSL_SMALL_STACK
+ password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
+ if (password == NULL)
+ return MEMORY_E;
+ #endif
+
+ /* get password */
+ ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
+ info->passwd_userdata);
+ if (ret >= 0) {
+ passwordSz = ret;
+
+ /* convert and adjust length */
+ if (header == BEGIN_ENC_PRIV_KEY) {
+ #ifndef NO_PWDBASED
+ ret = ToTraditionalEnc(der->buffer, der->length,
+ password, passwordSz, &algId);
+
+ if (ret >= 0) {
+ der->length = ret;
+ if (keyFormat) {
+ *keyFormat = algId;
+ }
+ ret = 0;
+ }
+ #else
+ ret = NOT_COMPILED_IN;
+ #endif
+ }
+ /* decrypt the key */
+ else {
+ if (passwordSz == 0) {
+ /* The key is encrypted but does not have a password */
+ WOLFSSL_MSG("No password for encrypted key");
+ ret = NO_PASSWORD;
+ }
+ else {
+ ret = wc_BufferKeyDecrypt(info, der->buffer, der->length,
+ (byte*)password, passwordSz, WC_MD5);
+
+#ifndef NO_WOLFSSL_SKIP_TRAILING_PAD
+ #ifndef NO_DES3
+ if (info->cipherType == WC_CIPHER_DES3) {
+ padVal = der->buffer[der->length-1];
+ if (padVal <= DES_BLOCK_SIZE) {
+ der->length -= padVal;
+ }
+ }
+ #endif /* !NO_DES3 */
+#endif /* !NO_WOLFSSL_SKIP_TRAILING_PAD */
+ }
+ }
+#ifdef OPENSSL_EXTRA
+ if (ret) {
+ PEMerr(0, PEM_R_BAD_DECRYPT);
+ }
+#endif
+ ForceZero(password, passwordSz);
+ }
+#ifdef OPENSSL_EXTRA
+ else {
+ PEMerr(0, PEM_R_BAD_PASSWORD_READ);
+ }
+#endif
+
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(password, heap, DYNAMIC_TYPE_STRING);
+ #endif
+ }
+#endif /* WOLFSSL_ENCRYPTED_KEYS */
+
+ return ret;
+}
+
+int wc_PemToDer(const unsigned char* buff, long longSz, int type,
+ DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey)
+{
+ return PemToDer(buff, longSz, type, pDer, heap, info, eccKey);
+}
+
+
+/* our KeyPemToDer password callback, password in userData */
+static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata)
+{
+ (void)rw;
+
+ if (userdata == NULL)
+ return 0;
+
+ XSTRNCPY(passwd, (char*)userdata, sz);
+ return min((word32)sz, (word32)XSTRLEN((char*)userdata));
+}
+
+/* Return bytes written to buff or < 0 for error */
+int wc_KeyPemToDer(const unsigned char* pem, int pemSz,
+ unsigned char* buff, int buffSz, const char* pass)
+{
+ int eccKey = 0;
+ int ret;
+ DerBuffer* der = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+ EncryptedInfo* info = NULL;
+#else
+ EncryptedInfo info[1];
+#endif
+
+ WOLFSSL_ENTER("wc_KeyPemToDer");
+
+ if (pem == NULL || buff == NULL || buffSz <= 0) {
+ WOLFSSL_MSG("Bad pem der args");
+ return BAD_FUNC_ARG;
+ }
+
+#ifdef WOLFSSL_SMALL_STACK
+ info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL,
+ DYNAMIC_TYPE_ENCRYPTEDINFO);
+ if (info == NULL)
+ return MEMORY_E;
+#endif
+
+ XMEMSET(info, 0, sizeof(EncryptedInfo));
+ info->passwd_cb = OurPasswordCb;
+ info->passwd_userdata = (void*)pass;
+
+ ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey);
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO);
+#endif
+
+ if (ret < 0 || der == NULL) {
+ WOLFSSL_MSG("Bad Pem To Der");
+ }
+ else {
+ if (der->length <= (word32)buffSz) {
+ XMEMCPY(buff, der->buffer, der->length);
+ ret = der->length;
+ }
+ else {
+ WOLFSSL_MSG("Bad der length");
+ ret = BAD_FUNC_ARG;
+ }
+ }
+
+ FreeDer(&der);
+ return ret;
+}
+
+
+/* Return bytes written to buff or < 0 for error */
+int wc_CertPemToDer(const unsigned char* pem, int pemSz,
+ unsigned char* buff, int buffSz, int type)
+{
+ int eccKey = 0;
+ int ret;
+ DerBuffer* der = NULL;
+
+ WOLFSSL_ENTER("wc_CertPemToDer");
+
+ if (pem == NULL || buff == NULL || buffSz <= 0) {
+ WOLFSSL_MSG("Bad pem der args");
+ return BAD_FUNC_ARG;
+ }
+
+ if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) {
+ WOLFSSL_MSG("Bad cert type");
+ return BAD_FUNC_ARG;
+ }
+
+
+ ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &eccKey);
+ if (ret < 0 || der == NULL) {
+ WOLFSSL_MSG("Bad Pem To Der");
+ }
+ else {
+ if (der->length <= (word32)buffSz) {
+ XMEMCPY(buff, der->buffer, der->length);
+ ret = der->length;
+ }
+ else {
+ WOLFSSL_MSG("Bad der length");
+ ret = BAD_FUNC_ARG;
+ }
+ }
+
+ FreeDer(&der);
+ return ret;
+}
+
+#endif /* WOLFSSL_PEM_TO_DER */
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
+
+
+#ifdef WOLFSSL_PEM_TO_DER
+#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
+/* Return bytes written to buff or < 0 for error */
+int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz,
+ unsigned char* buff, int buffSz)
+{
+ int ret;
+ DerBuffer* der = NULL;
+
+ WOLFSSL_ENTER("wc_PubKeyPemToDer");
+
+ if (pem == NULL || buff == NULL || buffSz <= 0) {
+ WOLFSSL_MSG("Bad pem der args");
+ return BAD_FUNC_ARG;
+ }
+
+ ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL);
+ if (ret < 0 || der == NULL) {
+ WOLFSSL_MSG("Bad Pem To Der");
+ }
+ else {
+ if (der->length <= (word32)buffSz) {
+ XMEMCPY(buff, der->buffer, der->length);
+ ret = der->length;
+ }
+ else {
+ WOLFSSL_MSG("Bad der length");
+ ret = BAD_FUNC_ARG;
+ }
+ }
+
+ FreeDer(&der);
+ return ret;
+}
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
+#endif /* WOLFSSL_PEM_TO_DER */
+
+#ifndef NO_FILESYSTEM
+
+#ifdef WOLFSSL_CERT_GEN
+/* load pem cert from file into der buffer, return der size or error */
+int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte staticBuffer[1]; /* force XMALLOC */
+#else
+ byte staticBuffer[FILE_BUFFER_SIZE];
+#endif
+ byte* fileBuf = staticBuffer;
+ int dynamic = 0;
+ int ret = 0;
+ long sz = 0;
+ XFILE file;
+ DerBuffer* converted = NULL;
+
+ WOLFSSL_ENTER("wc_PemCertToDer");
+
+ if (fileName == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ file = XFOPEN(fileName, "rb");
+ if (file == XBADFILE) {
+ ret = BUFFER_E;
+ }
+ }
+
+ if (ret == 0) {
+ if(XFSEEK(file, 0, XSEEK_END) != 0)
+ ret = BUFFER_E;
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz <= 0) {
+ ret = BUFFER_E;
+ }
+ else if (sz > (long)sizeof(staticBuffer)) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("File was larger then static buffer");
+ return MEMORY_E;
+ #endif
+ fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+ if (fileBuf == NULL)
+ ret = MEMORY_E;
+ else
+ dynamic = 1;
+ }
+
+ if (ret == 0) {
+ if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+ ret = BUFFER_E;
+ }
+ #ifdef WOLFSSL_PEM_TO_DER
+ else {
+ ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, NULL,NULL);
+ }
+ #endif
+
+ if (ret == 0) {
+ if (converted->length < (word32)derSz) {
+ XMEMCPY(derBuf, converted->buffer, converted->length);
+ ret = converted->length;
+ }
+ else
+ ret = BUFFER_E;
+ }
+
+ FreeDer(&converted);
+ }
+
+ XFCLOSE(file);
+ if (dynamic)
+ XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_CERT_GEN */
+
+#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)
+/* load pem public key from file into der buffer, return der size or error */
+int wc_PemPubKeyToDer(const char* fileName,
+ unsigned char* derBuf, int derSz)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte staticBuffer[1]; /* force XMALLOC */
+#else
+ byte staticBuffer[FILE_BUFFER_SIZE];
+#endif
+ byte* fileBuf = staticBuffer;
+ int dynamic = 0;
+ int ret = 0;
+ long sz = 0;
+ XFILE file;
+ DerBuffer* converted = NULL;
+
+ WOLFSSL_ENTER("wc_PemPubKeyToDer");
+
+ if (fileName == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ file = XFOPEN(fileName, "rb");
+ if (file == XBADFILE) {
+ ret = BUFFER_E;
+ }
+ }
+
+ if (ret == 0) {
+ if(XFSEEK(file, 0, XSEEK_END) != 0)
+ ret = BUFFER_E;
+ sz = XFTELL(file);
+ XREWIND(file);
+
+ if (sz <= 0) {
+ ret = BUFFER_E;
+ }
+ else if (sz > (long)sizeof(staticBuffer)) {
+ #ifdef WOLFSSL_STATIC_MEMORY
+ WOLFSSL_MSG("File was larger then static buffer");
+ return MEMORY_E;
+ #endif
+ fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
+ if (fileBuf == NULL)
+ ret = MEMORY_E;
+ else
+ dynamic = 1;
+ }
+ if (ret == 0) {
+ if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+ ret = BUFFER_E;
+ }
+ #ifdef WOLFSSL_PEM_TO_DER
+ else {
+ ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted,
+ 0, NULL, NULL);
+ }
+ #endif
+
+ if (ret == 0) {
+ if (converted->length < (word32)derSz) {
+ XMEMCPY(derBuf, converted->buffer, converted->length);
+ ret = converted->length;
+ }
+ else
+ ret = BUFFER_E;
+ }
+
+ FreeDer(&converted);
+ }
+
+ XFCLOSE(file);
+ if (dynamic)
+ XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE);
+ }
+
+ return ret;
+}
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */
+
+#endif /* !NO_FILESYSTEM */
+
+
+#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \
+ ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA)))
+/* USER RSA ifdef portions used instead of refactor in consideration for
+ possible fips build */
+/* Write a public RSA key to output */
+static int SetRsaPublicKey(byte* output, RsaKey* key,
+ int outLen, int with_header)
+{
+#ifdef WOLFSSL_SMALL_STACK
+ byte* n = NULL;
+ byte* e = NULL;
+#else
+ byte n[MAX_RSA_INT_SZ];
+ byte e[MAX_RSA_E_SZ];
+#endif
+ byte seq[MAX_SEQ_SZ];
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int nSz;
+ int eSz;
+ int seqSz;
+ int bitStringSz;
+ int idx;
+
+ if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ)
+ return BAD_FUNC_ARG;
+
+ /* n */
+#ifdef WOLFSSL_SMALL_STACK
+ n = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (n == NULL)
+ return MEMORY_E;
+#endif
+
+#ifdef HAVE_USER_RSA
+ nSz = SetASNIntRSA(key->n, n);
+#else
+ nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n);
+#endif
+ if (nSz < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return nSz;
+ }
+
+ /* e */
+#ifdef WOLFSSL_SMALL_STACK
+ e = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (e == NULL) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return MEMORY_E;
+ }
+#endif
+
+#ifdef HAVE_USER_RSA
+ eSz = SetASNIntRSA(key->e, e);
+#else
+ eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e);
+#endif
+ if (eSz < 0) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return eSz;
+ }
+
+ seqSz = SetSequence(nSz + eSz, seq);
+
+ /* check output size */
+ if ( (seqSz + nSz + eSz) > outLen) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return BUFFER_E;
+ }
+
+ /* headers */
+ if (with_header) {
+ int algoSz;
+#ifdef WOLFSSL_SMALL_STACK
+ byte* algo;
+
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
+#else
+ byte algo[MAX_ALGO_SZ];
+#endif
+ algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0);
+ bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString);
+
+ idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output);
+
+ /* check output size */
+ if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+
+ return BUFFER_E;
+ }
+
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ }
+ else
+ idx = 0;
+
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx += seqSz;
+ /* n */
+ XMEMCPY(output + idx, n, nSz);
+ idx += nSz;
+ /* e */
+ XMEMCPY(output + idx, e, eSz);
+ idx += eSz;
+
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return idx;
+}
+
+#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN &&
+ !HAVE_USER_RSA))) */
+
+#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA))
+int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header)
+{
+ int idx = 0;
+ int nSz, eSz, seqSz, bitStringSz, algoSz;
+
+ if (key == NULL)
+ return BAD_FUNC_ARG;
+
+ /* n */
+#ifdef HAVE_USER_RSA
+ nSz = SetASNIntRSA(key->n, NULL);
+#else
+ nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, NULL);
+#endif
+ if (nSz < 0) {
+ return nSz;
+ }
+
+ /* e */
+#ifdef HAVE_USER_RSA
+ eSz = SetASNIntRSA(key->e, NULL);
+#else
+ eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, NULL);
+#endif
+ if (eSz < 0) {
+ return eSz;
+ }
-#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */
+ seqSz = SetSequence(nSz + eSz, NULL);
+ /* headers */
+ if (with_header) {
+ algoSz = SetAlgoID(RSAk, NULL, oidKeyType, 0);
+ bitStringSz = SetBitString(seqSz + nSz + eSz, 0, NULL);
-#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA)
+ idx += SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, NULL);
+ /* algo */
+ idx += algoSz;
+ /* bit string */
+ idx += bitStringSz;
+ }
+
+ /* seq */
+ idx += seqSz;
+ /* n */
+ idx += nSz;
+ /* e */
+ idx += eSz;
+
+ return idx;
+}
+
+#endif /* !NO_RSA && WOLFSSL_CERT_GEN */
+
+
+#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
static mp_int* GetRsaInt(RsaKey* key, int idx)
{
@@ -4688,13 +11163,13 @@ static mp_int* GetRsaInt(RsaKey* key, int idx)
/* Release Tmp RSA resources */
-static INLINE void FreeTmpRsas(byte** tmps, void* heap)
+static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap)
{
int i;
(void)heap;
- for (i = 0; i < RSA_INTS; i++)
+ for (i = 0; i < RSA_INTS; i++)
XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA);
}
@@ -4705,13 +11180,13 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
{
word32 seqSz, verSz, rawLen, intTotalLen = 0;
word32 sizes[RSA_INTS];
- int i, j, outLen, ret = 0;
+ int i, j, outLen, ret = 0, mpSz;
byte seq[MAX_SEQ_SZ];
byte ver[MAX_VERSION_SZ];
byte* tmps[RSA_INTS];
- if (!key || !output)
+ if (!key)
return BAD_FUNC_ARG;
if (key->type != RSA_PRIVATE)
@@ -4723,7 +11198,8 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
/* write all big ints from key to DER tmps */
for (i = 0; i < RSA_INTS; i++) {
mp_int* keyInt = GetRsaInt(key, i);
- rawLen = mp_unsigned_bin_size(keyInt);
+
+ rawLen = mp_unsigned_bin_size(keyInt) + 1;
tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap,
DYNAMIC_TYPE_RSA);
if (tmps[i] == NULL) {
@@ -4731,24 +11207,12 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
break;
}
- tmps[i][0] = ASN_INTEGER;
- sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1; /* int tag */
-
- if (sizes[i] <= MAX_SEQ_SZ) {
- int err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]);
- if (err == MP_OKAY) {
- sizes[i] += rawLen;
- intTotalLen += sizes[i];
- }
- else {
- ret = err;
- break;
- }
- }
- else {
- ret = ASN_INPUT_E;
+ mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]);
+ if (mpSz < 0) {
+ ret = mpSz;
break;
}
+ intTotalLen += (sizes[i] = mpSz);
}
if (ret != 0) {
@@ -4761,42 +11225,43 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
seqSz = SetSequence(verSz + intTotalLen, seq);
outLen = seqSz + verSz + intTotalLen;
- if (outLen > (int)inLen)
- return BAD_FUNC_ARG;
+ if (output) {
+ if (outLen > (int)inLen) {
+ FreeTmpRsas(tmps, key->heap);
+ return BAD_FUNC_ARG;
+ }
- /* write to output */
- XMEMCPY(output, seq, seqSz);
- j = seqSz;
- XMEMCPY(output + j, ver, verSz);
- j += verSz;
+ /* write to output */
+ XMEMCPY(output, seq, seqSz);
+ j = seqSz;
+ XMEMCPY(output + j, ver, verSz);
+ j += verSz;
- for (i = 0; i < RSA_INTS; i++) {
- XMEMCPY(output + j, tmps[i], sizes[i]);
- j += sizes[i];
+ for (i = 0; i < RSA_INTS; i++) {
+ XMEMCPY(output + j, tmps[i], sizes[i]);
+ j += sizes[i];
+ }
}
FreeTmpRsas(tmps, key->heap);
return outLen;
}
+#endif
-#endif /* WOLFSSL_KEY_GEN && !NO_RSA */
-
-
-#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA)
-
-
-#ifndef WOLFSSL_HAVE_MIN
-#define WOLFSSL_HAVE_MIN
+#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+/* Convert Rsa Public key to DER format, write to output (inLen), return bytes
+ written */
+int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen)
+{
+ return SetRsaPublicKey(output, key, inLen, 1);
+}
- static INLINE word32 min(word32 a, word32 b)
- {
- return a > b ? b : a;
- }
+#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA && !HAVE_USER_RSA */
-#endif /* WOLFSSL_HAVE_MIN */
+#ifdef WOLFSSL_CERT_GEN
-/* Initialize and Set Certficate defaults:
+/* Initialize and Set Certificate defaults:
version = 3 (0x2)
serial = 0
sigType = SHA_WITH_RSA
@@ -4805,57 +11270,57 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen)
selfSigned = 1 (true) use subject as issuer
subject = blank
*/
-void wc_InitCert(Cert* cert)
+int wc_InitCert(Cert* cert)
{
+#ifdef WOLFSSL_MULTI_ATTRIB
+ int i = 0;
+#endif
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ XMEMSET(cert, 0, sizeof(Cert));
+
cert->version = 2; /* version 3 is hex 2 */
+#ifndef NO_SHA
cert->sigType = CTC_SHAwRSA;
+#elif !defined(NO_SHA256)
+ cert->sigType = CTC_SHA256wRSA;
+#else
+ cert->sigType = 0;
+#endif
cert->daysValid = 500;
cert->selfSigned = 1;
- cert->isCA = 0;
- cert->bodySz = 0;
-#ifdef WOLFSSL_ALT_NAMES
- cert->altNamesSz = 0;
- cert->beforeDateSz = 0;
- cert->afterDateSz = 0;
-#endif
cert->keyType = RSA_KEY;
- XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE);
- cert->issuer.country[0] = '\0';
cert->issuer.countryEnc = CTC_PRINTABLE;
- cert->issuer.state[0] = '\0';
cert->issuer.stateEnc = CTC_UTF8;
- cert->issuer.locality[0] = '\0';
cert->issuer.localityEnc = CTC_UTF8;
- cert->issuer.sur[0] = '\0';
cert->issuer.surEnc = CTC_UTF8;
- cert->issuer.org[0] = '\0';
cert->issuer.orgEnc = CTC_UTF8;
- cert->issuer.unit[0] = '\0';
cert->issuer.unitEnc = CTC_UTF8;
- cert->issuer.commonName[0] = '\0';
cert->issuer.commonNameEnc = CTC_UTF8;
- cert->issuer.email[0] = '\0';
- cert->subject.country[0] = '\0';
cert->subject.countryEnc = CTC_PRINTABLE;
- cert->subject.state[0] = '\0';
cert->subject.stateEnc = CTC_UTF8;
- cert->subject.locality[0] = '\0';
cert->subject.localityEnc = CTC_UTF8;
- cert->subject.sur[0] = '\0';
cert->subject.surEnc = CTC_UTF8;
- cert->subject.org[0] = '\0';
cert->subject.orgEnc = CTC_UTF8;
- cert->subject.unit[0] = '\0';
cert->subject.unitEnc = CTC_UTF8;
- cert->subject.commonName[0] = '\0';
cert->subject.commonNameEnc = CTC_UTF8;
- cert->subject.email[0] = '\0';
-#ifdef WOLFSSL_CERT_REQ
- cert->challengePw[0] ='\0';
+#ifdef WOLFSSL_MULTI_ATTRIB
+ for (i = 0; i < CTC_MAX_ATTRIB; i++) {
+ cert->issuer.name[i].type = CTC_UTF8;
+ cert->subject.name[i].type = CTC_UTF8;
+ }
+#endif /* WOLFSSL_MULTI_ATTRIB */
+
+#ifdef WOLFSSL_HEAP_TEST
+ cert->heap = (void*)WOLFSSL_HEAP_TEST;
#endif
+
+ return 0;
}
@@ -4863,26 +11328,46 @@ void wc_InitCert(Cert* cert)
typedef struct DerCert {
byte size[MAX_LENGTH_SZ]; /* length encoded */
byte version[MAX_VERSION_SZ]; /* version encoded */
- byte serial[CTC_SERIAL_SIZE + MAX_LENGTH_SZ]; /* serial number encoded */
+ byte serial[(int)CTC_SERIAL_SIZE + (int)MAX_LENGTH_SZ]; /* serial number encoded */
byte sigAlgo[MAX_ALGO_SZ]; /* signature algo encoded */
byte issuer[ASN_NAME_MAX]; /* issuer encoded */
byte subject[ASN_NAME_MAX]; /* subject encoded */
byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */
byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */
byte ca[MAX_CA_SZ]; /* basic constraint CA true size */
- byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */
+ byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */
+#ifdef WOLFSSL_CERT_EXT
+ byte skid[MAX_KID_SZ]; /* Subject Key Identifier extension */
+ byte akid[MAX_KID_SZ]; /* Authority Key Identifier extension */
+ byte keyUsage[MAX_KEYUSAGE_SZ]; /* Key Usage extension */
+ byte extKeyUsage[MAX_EXTKEYUSAGE_SZ]; /* Extended Key Usage extension */
+ byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */
+#endif
#ifdef WOLFSSL_CERT_REQ
byte attrib[MAX_ATTRIB_SZ]; /* Cert req attributes encoded */
#endif
+#ifdef WOLFSSL_ALT_NAMES
+ byte altNames[CTC_MAX_ALT_SIZE]; /* Alternative Names encoded */
+#endif
int sizeSz; /* encoded size length */
int versionSz; /* encoded version length */
int serialSz; /* encoded serial length */
- int sigAlgoSz; /* enocded sig alog length */
+ int sigAlgoSz; /* encoded sig algo length */
int issuerSz; /* encoded issuer length */
int subjectSz; /* encoded subject length */
int validitySz; /* encoded validity length */
int publicKeySz; /* encoded public key length */
int caSz; /* encoded CA extension length */
+#ifdef WOLFSSL_CERT_EXT
+ int skidSz; /* encoded SKID extension length */
+ int akidSz; /* encoded SKID extension length */
+ int keyUsageSz; /* encoded KeyUsage extension length */
+ int extKeyUsageSz; /* encoded ExtendedKeyUsage extension length */
+ int certPoliciesSz; /* encoded CertPolicies extension length*/
+#endif
+#ifdef WOLFSSL_ALT_NAMES
+ int altNamesSz; /* encoded AltNames extension length */
+#endif
int extensionsSz; /* encoded extensions total length */
int total; /* total encoded lengths */
#ifdef WOLFSSL_CERT_REQ
@@ -4894,6 +11379,12 @@ typedef struct DerCert {
#ifdef WOLFSSL_CERT_REQ
/* Write a set header to output */
+static word32 SetPrintableString(word32 len, byte* output)
+{
+ output[0] = ASN_PRINTABLE_STRING;
+ return SetLength(len, output + 1) + 1;
+}
+
static word32 SetUTF8String(word32 len, byte* output)
{
output[0] = ASN_UTF8STRING;
@@ -4903,258 +11394,444 @@ static word32 SetUTF8String(word32 len, byte* output)
#endif /* WOLFSSL_CERT_REQ */
-/* Write a serial number to output */
-static int SetSerial(const byte* serial, byte* output)
+#ifndef WOLFSSL_CERT_GEN_CACHE
+/* wc_SetCert_Free is only public when WOLFSSL_CERT_GEN_CACHE is not defined */
+static
+#endif
+void wc_SetCert_Free(Cert* cert)
{
- int length = 0;
+ if (cert != NULL) {
+ cert->der = NULL;
+ if (cert->decodedCert) {
+ FreeDecodedCert((DecodedCert*)cert->decodedCert);
+
+ XFREE(cert->decodedCert, cert->heap, DYNAMIC_TYPE_DCERT);
+ cert->decodedCert = NULL;
+ }
+ }
+}
+
+static int wc_SetCert_LoadDer(Cert* cert, const byte* der, word32 derSz)
+{
+ int ret;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Allocate DecodedCert struct and Zero */
+ cert->decodedCert = (void*)XMALLOC(sizeof(DecodedCert), cert->heap,
+ DYNAMIC_TYPE_DCERT);
- output[length++] = ASN_INTEGER;
- length += SetLength(CTC_SERIAL_SIZE, &output[length]);
- XMEMCPY(&output[length], serial, CTC_SERIAL_SIZE);
+ if (cert->decodedCert == NULL) {
+ ret = MEMORY_E;
+ }
+ else {
+ XMEMSET(cert->decodedCert, 0, sizeof(DecodedCert));
+
+ InitDecodedCert((DecodedCert*)cert->decodedCert, der, derSz,
+ cert->heap);
+ ret = ParseCertRelative((DecodedCert*)cert->decodedCert,
+ CERT_TYPE, 0, NULL);
+ if (ret >= 0) {
+ cert->der = (byte*)der;
+ }
+ else {
+ wc_SetCert_Free(cert);
+ }
+ }
+ }
- return length + CTC_SERIAL_SIZE;
+ return ret;
}
+#endif /* WOLFSSL_CERT_GEN */
-#ifdef HAVE_ECC
+#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
/* Write a public ECC key to output */
-static int SetEccPublicKey(byte* output, ecc_key* key)
+static int SetEccPublicKey(byte* output, ecc_key* key, int with_header)
{
- byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
int algoSz;
int curveSz;
- int lenSz;
+ int bitStringSz;
int idx;
word32 pubSz = ECC_BUFSIZE;
#ifdef WOLFSSL_SMALL_STACK
byte* algo = NULL;
byte* curve = NULL;
- byte* pub = NULL;
+ byte* pub;
#else
byte algo[MAX_ALGO_SZ];
byte curve[MAX_ALGO_SZ];
byte pub[ECC_BUFSIZE];
#endif
+ int ret;
#ifdef WOLFSSL_SMALL_STACK
- pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ pub = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (pub == NULL)
return MEMORY_E;
#endif
- int ret = wc_ecc_export_x963(key, pub, &pubSz);
+#ifdef HAVE_SELFTEST
+ /* older version of ecc.c can not handle dp being NULL */
+ if (key != NULL && key->dp == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ ret = wc_ecc_export_x963(key, pub, &pubSz);
+ }
+#else
+ ret = wc_ecc_export_x963(key, pub, &pubSz);
+#endif
if (ret != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
+ /* headers */
+ if (with_header) {
#ifdef WOLFSSL_SMALL_STACK
- curve = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (curve == NULL) {
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
+ curve = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (curve == NULL) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
-
- /* headers */
- curveSz = SetCurve(key, curve);
- if (curveSz <= 0) {
+ curveSz = SetCurve(key, curve);
+ if (curveSz <= 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return curveSz;
- }
+ return curveSz;
+ }
#ifdef WOLFSSL_SMALL_STACK
- algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (algo == NULL) {
- XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
- }
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
+ algoSz = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz);
+
+ bitStringSz = SetBitString(pubSz, 0, bitString);
+
+ idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output);
+ /* algo */
+ if (output)
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* curve */
+ if (output)
+ XMEMCPY(output + idx, curve, curveSz);
+ idx += curveSz;
+ /* bit string */
+ if (output)
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
+ }
+ else
+ idx = 0;
- algoSz = SetAlgoID(ECDSAk, algo, keyType, curveSz);
- lenSz = SetLength(pubSz + 1, len);
- len[lenSz++] = 0; /* trailing 0 */
-
- /* write */
- idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output);
- /* 1 is for ASN_BIT_STRING */
- /* algo */
- XMEMCPY(output + idx, algo, algoSz);
- idx += algoSz;
- /* curve */
- XMEMCPY(output + idx, curve, curveSz);
- idx += curveSz;
- /* bit string */
- output[idx++] = ASN_BIT_STRING;
- /* length */
- XMEMCPY(output + idx, len, lenSz);
- idx += lenSz;
/* pub */
- XMEMCPY(output + idx, pub, pubSz);
+ if (output)
+ XMEMCPY(output + idx, pub, pubSz);
idx += pubSz;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (with_header) {
+ XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return idx;
}
-#endif /* HAVE_ECC */
+/* returns the size of buffer used, the public ECC key in DER format is stored
+ in output buffer
+ with_AlgCurve is a flag for when to include a header that has the Algorithm
+ and Curve information */
+int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen,
+ int with_AlgCurve)
+{
+ word32 infoSz = 0;
+ word32 keySz = 0;
+ int ret;
+ if (key == NULL) {
+ return BAD_FUNC_ARG;
+ }
-/* Write a public RSA key to output */
-static int SetRsaPublicKey(byte* output, RsaKey* key)
+ if (with_AlgCurve) {
+ /* buffer space for algorithm/curve */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += 2 * MAX_ALGO_SZ;
+
+ /* buffer space for public key sequence */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += TRAILING_ZERO;
+ }
+
+#ifdef HAVE_SELFTEST
+ /* older version of ecc.c can not handle dp being NULL */
+ if (key != NULL && key->dp == NULL) {
+ keySz = 1 + 2 * MAX_ECC_BYTES;
+ ret = LENGTH_ONLY_E;
+ }
+ else {
+ ret = wc_ecc_export_x963(key, NULL, &keySz);
+ }
+#else
+ ret = wc_ecc_export_x963(key, NULL, &keySz);
+#endif
+ if (ret != LENGTH_ONLY_E) {
+ WOLFSSL_MSG("Error in getting ECC public key size");
+ return ret;
+ }
+
+ /* if output null then just return size */
+ if (output == NULL) {
+ return keySz + infoSz;
+ }
+
+ if (inLen < keySz + infoSz) {
+ return BUFFER_E;
+ }
+
+ return SetEccPublicKey(output, key, with_AlgCurve);
+}
+
+int wc_EccPublicKeyDerSize(ecc_key* key, int with_AlgCurve)
+{
+ return wc_EccPublicKeyToDer(key, NULL, 0, with_AlgCurve);
+}
+
+#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
+
+#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \
+ defined(WOLFSSL_KEY_GEN))
+
+/* Write a public ECC key to output */
+static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header)
{
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int algoSz;
+ int bitStringSz;
+ int idx;
+ word32 pubSz = ED25519_PUB_KEY_SIZE;
#ifdef WOLFSSL_SMALL_STACK
- byte* n = NULL;
- byte* e = NULL;
byte* algo = NULL;
+ byte* pub;
#else
- byte n[MAX_RSA_INT_SZ];
- byte e[MAX_RSA_E_SZ];
byte algo[MAX_ALGO_SZ];
+ byte pub[ED25519_PUB_KEY_SIZE];
#endif
- byte seq[MAX_SEQ_SZ];
- byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */
- int nSz;
- int eSz;
- int algoSz;
- int seqSz;
- int lenSz;
- int idx;
- int rawLen;
- int leadingBit;
- int err;
- /* n */
#ifdef WOLFSSL_SMALL_STACK
- n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (n == NULL)
+ pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pub == NULL)
return MEMORY_E;
#endif
- leadingBit = mp_leading_bit(&key->n);
- rawLen = mp_unsigned_bin_size(&key->n) + leadingBit;
- n[0] = ASN_INTEGER;
- nSz = SetLength(rawLen, n + 1) + 1; /* int tag */
-
- if ( (nSz + rawLen) < MAX_RSA_INT_SZ) {
- if (leadingBit)
- n[nSz] = 0;
- err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit);
- if (err == MP_OKAY)
- nSz += rawLen;
- else {
+ idx = wc_ed25519_export_public(key, pub, &pubSz);
+ if (idx != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return MP_TO_E;
+ return idx;
+ }
+
+ /* headers */
+ if (with_header) {
+#ifdef WOLFSSL_SMALL_STACK
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
}
+#endif
+ algoSz = SetAlgoID(ED25519k, algo, oidKeyType, 0);
+
+ bitStringSz = SetBitString(pubSz, 0, bitString);
+
+ idx = SetSequence(pubSz + bitStringSz + algoSz, output);
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
}
- else {
+ else
+ idx = 0;
+
+ /* pub */
+ XMEMCPY(output + idx, pub, pubSz);
+ idx += pubSz;
+
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (with_header) {
+ XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
+
+ return idx;
+}
+
+int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen,
+ int withAlg)
+{
+ word32 infoSz = 0;
+ word32 keySz = 0;
+ int ret;
+
+ if (output == NULL || key == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ if (withAlg) {
+ /* buffer space for algorithm */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += MAX_ALGO_SZ;
+
+ /* buffer space for public key sequence */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += TRAILING_ZERO;
+ }
+
+ if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) {
+ WOLFSSL_MSG("Error in getting ECC public key size");
+ return ret;
+ }
+
+ if (inLen < keySz + infoSz) {
return BUFFER_E;
}
- /* e */
-#ifdef WOLFSSL_SMALL_STACK
- e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (e == NULL) {
+ return SetEd25519PublicKey(output, key, withAlg);
+}
+#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
+#if defined(HAVE_ED448) && (defined(WOLFSSL_CERT_GEN) || \
+ defined(WOLFSSL_KEY_GEN))
+
+/* Write a public ECC key to output */
+static int SetEd448PublicKey(byte* output, ed448_key* key, int with_header)
+{
+ byte bitString[1 + MAX_LENGTH_SZ + 1];
+ int algoSz;
+ int bitStringSz;
+ int idx;
+ word32 pubSz = ED448_PUB_KEY_SIZE;
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ byte* algo = NULL;
+ byte* pub = NULL;
+#else
+ byte algo[MAX_ALGO_SZ];
+ byte pub[ED448_PUB_KEY_SIZE];
#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+ pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pub == NULL)
return MEMORY_E;
- }
#endif
- leadingBit = mp_leading_bit(&key->e);
- rawLen = mp_unsigned_bin_size(&key->e) + leadingBit;
- e[0] = ASN_INTEGER;
- eSz = SetLength(rawLen, e + 1) + 1; /* int tag */
-
- if ( (eSz + rawLen) < MAX_RSA_E_SZ) {
- if (leadingBit)
- e[eSz] = 0;
- err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit);
- if (err == MP_OKAY)
- eSz += rawLen;
- else {
+ idx = wc_ed448_export_public(key, pub, &pubSz);
+ if (idx != 0) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- return MP_TO_E;
- }
+ return idx;
}
- else {
+
+ /* headers */
+ if (with_header) {
#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ if (algo == NULL) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
#endif
- return BUFFER_E;
+ algoSz = SetAlgoID(ED448k, algo, oidKeyType, 0);
+
+ bitStringSz = SetBitString(pubSz, 0, bitString);
+
+ idx = SetSequence(pubSz + bitStringSz + algoSz, output);
+ /* algo */
+ XMEMCPY(output + idx, algo, algoSz);
+ idx += algoSz;
+ /* bit string */
+ XMEMCPY(output + idx, bitString, bitStringSz);
+ idx += bitStringSz;
}
+ else
+ idx = 0;
+
+ /* pub */
+ XMEMCPY(output + idx, pub, pubSz);
+ idx += pubSz;
#ifdef WOLFSSL_SMALL_STACK
- algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (algo == NULL) {
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- return MEMORY_E;
+ if (with_header) {
+ XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
+ XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
- /* headers */
- algoSz = SetAlgoID(RSAk, algo, keyType, 0);
- seqSz = SetSequence(nSz + eSz, seq);
- lenSz = SetLength(seqSz + nSz + eSz + 1, len);
- len[lenSz++] = 0; /* trailing 0 */
+ return idx;
+}
- /* write */
- idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output);
- /* 1 is for ASN_BIT_STRING */
- /* algo */
- XMEMCPY(output + idx, algo, algoSz);
- idx += algoSz;
- /* bit string */
- output[idx++] = ASN_BIT_STRING;
- /* length */
- XMEMCPY(output + idx, len, lenSz);
- idx += lenSz;
- /* seq */
- XMEMCPY(output + idx, seq, seqSz);
- idx += seqSz;
- /* n */
- XMEMCPY(output + idx, n, nSz);
- idx += nSz;
- /* e */
- XMEMCPY(output + idx, e, eSz);
- idx += eSz;
+int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen,
+ int withAlg)
+{
+ word32 infoSz = 0;
+ word32 keySz = 0;
+ int ret;
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ if (output == NULL || key == NULL) {
+ return BAD_FUNC_ARG;
+ }
- return idx;
+ if (withAlg) {
+ /* buffer space for algorithm */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += MAX_ALGO_SZ;
+
+ /* buffer space for public key sequence */
+ infoSz += MAX_SEQ_SZ;
+ infoSz += TRAILING_ZERO;
+ }
+
+ if ((ret = wc_ed448_export_public(key, output, &keySz)) != BUFFER_E) {
+ WOLFSSL_MSG("Error in getting ECC public key size");
+ return ret;
+ }
+
+ if (inLen < keySz + infoSz) {
+ return BUFFER_E;
+ }
+
+ return SetEd448PublicKey(output, key, withAlg);
}
+#endif /* HAVE_ED448 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
+
+#ifdef WOLFSSL_CERT_GEN
-static INLINE byte itob(int number)
+static WC_INLINE byte itob(int number)
{
return (byte)number + 0x30;
}
@@ -5184,7 +11861,7 @@ static void SetTime(struct tm* date, byte* output)
output[i++] = itob(date->tm_sec / 10);
output[i++] = itob(date->tm_sec % 10);
-
+
output[i] = 'Z'; /* Zulu profile */
}
@@ -5200,28 +11877,19 @@ static int CopyValidity(byte* output, Cert* cert)
/* headers and output */
seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output);
- XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
- XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
- cert->afterDateSz);
+ if (output) {
+ XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz);
+ XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate,
+ cert->afterDateSz);
+ }
return seqSz + cert->beforeDateSz + cert->afterDateSz;
}
#endif
-/* for systems where mktime() doesn't normalize fully */
-static void RebuildTime(time_t* in, struct tm* out)
-{
- #ifdef FREESCALE_MQX
- out = localtime_r(in, out);
- #else
- (void)in;
- (void)out;
- #endif
-}
-
-
-/* Set Date validity from now until now + daysValid */
+/* Set Date validity from now until now + daysValid
+ * return size in bytes written to output, 0 on error */
static int SetValidity(byte* output, int daysValid)
{
byte before[MAX_DATE_SIZE];
@@ -5231,55 +11899,60 @@ static int SetValidity(byte* output, int daysValid)
int afterSz;
int seqSz;
- time_t ticks;
- time_t normalTime;
- struct tm* now;
- struct tm* tmpTime = NULL;
- struct tm local;
+ time_t now;
+ time_t then;
+ struct tm* tmpTime;
+ struct tm* expandedTime;
+ struct tm localTime;
-#if defined(FREESCALE_MQX) || defined(TIME_OVERRIDES)
+#if defined(NEED_TMP_TIME)
/* for use with gmtime_r */
struct tm tmpTimeStorage;
tmpTime = &tmpTimeStorage;
#else
- (void)tmpTime;
+ tmpTime = NULL;
#endif
+ (void)tmpTime;
- ticks = XTIME(0);
- now = XGMTIME(&ticks, tmpTime);
+ now = XTIME(0);
/* before now */
- local = *now;
before[0] = ASN_GENERALIZED_TIME;
- beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */
-
- /* subtract 1 day for more compliance */
- local.tm_mday -= 1;
- normalTime = mktime(&local);
- RebuildTime(&normalTime, &local);
+ beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */
+
+ /* subtract 1 day of seconds for more compliance */
+ then = now - 86400;
+ expandedTime = XGMTIME(&then, tmpTime);
+ if (expandedTime == NULL) {
+ WOLFSSL_MSG("XGMTIME failed");
+ return 0; /* error */
+ }
+ localTime = *expandedTime;
/* adjust */
- local.tm_year += 1900;
- local.tm_mon += 1;
+ localTime.tm_year += 1900;
+ localTime.tm_mon += 1;
- SetTime(&local, before + beforeSz);
+ SetTime(&localTime, before + beforeSz);
beforeSz += ASN_GEN_TIME_SZ;
- /* after now + daysValid */
- local = *now;
after[0] = ASN_GENERALIZED_TIME;
afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */
- /* add daysValid */
- local.tm_mday += daysValid;
- normalTime = mktime(&local);
- RebuildTime(&normalTime, &local);
+ /* add daysValid of seconds */
+ then = now + (daysValid * (time_t)86400);
+ expandedTime = XGMTIME(&then, tmpTime);
+ if (expandedTime == NULL) {
+ WOLFSSL_MSG("XGMTIME failed");
+ return 0; /* error */
+ }
+ localTime = *expandedTime;
/* adjust */
- local.tm_year += 1900;
- local.tm_mon += 1;
+ localTime.tm_year += 1900;
+ localTime.tm_mon += 1;
- SetTime(&local, after + afterSz);
+ SetTime(&localTime, after + afterSz);
afterSz += ASN_GEN_TIME_SZ;
/* headers and output */
@@ -5327,6 +12000,16 @@ static const char* GetOneName(CertName* name, int idx)
return name->commonName;
case 7:
+ return name->serialDev;
+
+#ifdef WOLFSSL_CERT_EXT
+ case 8:
+ return name->busCat;
+
+ case 9:
+#else
+ case 8:
+#endif
return name->email;
default:
@@ -5360,6 +12043,20 @@ static char GetNameType(CertName* name, int idx)
case 6:
return name->commonNameEnc;
+ case 7:
+ return name->serialDevEnc;
+
+#ifdef WOLFSSL_CERT_EXT
+ case 8:
+ return name->busCatEnc;
+
+ case 9:
+#else
+ case 8:
+#endif
+ /* FALL THROUGH */
+ /* The last index, email name, does not have encoding type.
+ The empty case here is to keep track of it for future reference. */
default:
return 0;
}
@@ -5392,54 +12089,589 @@ static byte GetNameId(int idx)
return ASN_COMMON_NAME;
case 7:
- /* email uses different id type */
- return 0;
+ return ASN_SERIAL_NUMBER;
+
+#ifdef WOLFSSL_CERT_EXT
+ case 8:
+ return ASN_BUS_CAT;
+
+ case 9:
+#else
+ case 8:
+#endif
+ return ASN_EMAIL_NAME;
default:
return 0;
}
}
+/*
+ Extensions ::= SEQUENCE OF Extension
+
+ Extension ::= SEQUENCE {
+ extnId OBJECT IDENTIFIER,
+ critical BOOLEAN DEFAULT FALSE,
+ extnValue OCTET STRING }
+ */
/* encode all extensions, return total bytes written */
-static int SetExtensions(byte* output, const byte* ext, int extSz, int header)
+static int SetExtensions(byte* out, word32 outSz, int *IdxInOut,
+ const byte* ext, int extSz)
+{
+ if (out == NULL || IdxInOut == NULL || ext == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < (word32)(*IdxInOut+extSz))
+ return BUFFER_E;
+
+ XMEMCPY(&out[*IdxInOut], ext, extSz); /* extensions */
+ *IdxInOut += extSz;
+
+ return *IdxInOut;
+}
+
+/* encode extensions header, return total bytes written */
+static int SetExtensionsHeader(byte* out, word32 outSz, int extSz)
{
byte sequence[MAX_SEQ_SZ];
byte len[MAX_LENGTH_SZ];
+ int seqSz, lenSz, idx = 0;
- int sz = 0;
- int seqSz = SetSequence(extSz, sequence);
+ if (out == NULL)
+ return BAD_FUNC_ARG;
- if (header) {
- int lenSz = SetLength(seqSz + extSz, len);
- output[0] = ASN_EXTENSIONS; /* extensions id */
- sz++;
- XMEMCPY(&output[sz], len, lenSz); /* length */
- sz += lenSz;
- }
- XMEMCPY(&output[sz], sequence, seqSz); /* sequence */
- sz += seqSz;
- XMEMCPY(&output[sz], ext, extSz); /* extensions */
- sz += extSz;
+ if (outSz < 3)
+ return BUFFER_E;
- return sz;
+ seqSz = SetSequence(extSz, sequence);
+
+ /* encode extensions length provided */
+ lenSz = SetLength(extSz+seqSz, len);
+
+ if (outSz < (word32)(lenSz+seqSz+1))
+ return BUFFER_E;
+
+ out[idx++] = ASN_EXTENSIONS; /* extensions id */
+ XMEMCPY(&out[idx], len, lenSz); /* length */
+ idx += lenSz;
+
+ XMEMCPY(&out[idx], sequence, seqSz); /* sequence */
+ idx += seqSz;
+
+ return idx;
}
/* encode CA basic constraint true, return total bytes written */
-static int SetCa(byte* output)
+static int SetCa(byte* out, word32 outSz)
{
- static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
+ const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
0x05, 0x30, 0x03, 0x01, 0x01, 0xff };
-
- XMEMCPY(output, ca, sizeof(ca));
+
+ if (out == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < sizeof(ca))
+ return BUFFER_E;
+
+ XMEMCPY(out, ca, sizeof(ca));
return (int)sizeof(ca);
}
+#ifdef WOLFSSL_CERT_EXT
+/* encode OID and associated value, return total bytes written */
+static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz,
+ byte *in, word32 inSz)
+{
+ int idx = 0;
+
+ if (out == NULL || oid == NULL || in == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < 3)
+ return BUFFER_E;
+
+ /* sequence, + 1 => byte to put value size */
+ idx = SetSequence(inSz + oidSz + 1, out);
+
+ if ((idx + inSz + oidSz + 1) > outSz)
+ return BUFFER_E;
+
+ XMEMCPY(out+idx, oid, oidSz);
+ idx += oidSz;
+ out[idx++] = (byte)inSz;
+ XMEMCPY(out+idx, in, inSz);
+
+ return (idx+inSz);
+}
+
+/* encode Subject Key Identifier, return total bytes written
+ * RFC5280 : non-critical */
+static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length)
+{
+ byte skid_len[1 + MAX_LENGTH_SZ];
+ byte skid_enc_len[MAX_LENGTH_SZ];
+ int idx = 0, skid_lenSz, skid_enc_lenSz;
+ const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 };
+
+ if (output == NULL || input == NULL)
+ return BAD_FUNC_ARG;
+
+ /* Octet String header */
+ skid_lenSz = SetOctetString(length, skid_len);
+
+ /* length of encoded value */
+ skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len);
+
+ if (outSz < 3)
+ return BUFFER_E;
+
+ idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz,
+ output);
+
+ if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz)
+ return BUFFER_E;
+
+ /* put oid */
+ XMEMCPY(output+idx, skid_oid, sizeof(skid_oid));
+ idx += sizeof(skid_oid);
+
+ /* put encoded len */
+ XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz);
+ idx += skid_enc_lenSz;
+
+ /* put octet header */
+ XMEMCPY(output+idx, skid_len, skid_lenSz);
+ idx += skid_lenSz;
+
+ /* put value */
+ XMEMCPY(output+idx, input, length);
+ idx += length;
+
+ return idx;
+}
+
+/* encode Authority Key Identifier, return total bytes written
+ * RFC5280 : non-critical */
+static int SetAKID(byte* output, word32 outSz,
+ byte *input, word32 length, void* heap)
+{
+ byte *enc_val;
+ int ret, enc_valSz;
+ const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 };
+ const byte akid_cs[] = { 0x80 };
+
+ (void)heap;
+
+ if (output == NULL || input == NULL)
+ return BAD_FUNC_ARG;
+
+ enc_valSz = length + 3 + sizeof(akid_cs);
+ enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (enc_val == NULL)
+ return MEMORY_E;
+
+ /* sequence for ContentSpec & value */
+ ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs),
+ input, length);
+ if (ret > 0) {
+ enc_valSz = ret;
+
+ ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid),
+ enc_val, enc_valSz);
+ }
+
+ XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+/* encode Key Usage, return total bytes written
+ * RFC5280 : critical */
+static int SetKeyUsage(byte* output, word32 outSz, word16 input)
+{
+ byte ku[5];
+ int idx;
+ const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f,
+ 0x01, 0x01, 0xff, 0x04};
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
+ idx = SetBitString16Bit(input, ku);
+ return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid),
+ ku, idx);
+}
+
+static int SetOjectIdValue(byte* output, word32 outSz, int* idx,
+ const byte* oid, word32 oidSz)
+{
+ /* verify room */
+ if (*idx + 2 + oidSz >= outSz)
+ return ASN_PARSE_E;
+
+ *idx += SetObjectId(oidSz, &output[*idx]);
+ XMEMCPY(&output[*idx], oid, oidSz);
+ *idx += oidSz;
+
+ return 0;
+}
+
+/* encode Extended Key Usage (RFC 5280 4.2.1.12), return total bytes written */
+static int SetExtKeyUsage(Cert* cert, byte* output, word32 outSz, byte input)
+{
+ int idx = 0, oidListSz = 0, totalSz, ret = 0;
+ const byte extkeyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x25 };
+
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
+ /* Skip to OID List */
+ totalSz = 2 + sizeof(extkeyusage_oid) + 4;
+ idx = totalSz;
+
+ /* Build OID List */
+ /* If any set, then just use it */
+ if (input & EXTKEYUSE_ANY) {
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageAnyOid, sizeof(extExtKeyUsageAnyOid));
+ }
+ else {
+ if (input & EXTKEYUSE_SERVER_AUTH)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageServerAuthOid, sizeof(extExtKeyUsageServerAuthOid));
+ if (input & EXTKEYUSE_CLIENT_AUTH)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageClientAuthOid, sizeof(extExtKeyUsageClientAuthOid));
+ if (input & EXTKEYUSE_CODESIGN)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageCodeSigningOid, sizeof(extExtKeyUsageCodeSigningOid));
+ if (input & EXTKEYUSE_EMAILPROT)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageEmailProtectOid, sizeof(extExtKeyUsageEmailProtectOid));
+ if (input & EXTKEYUSE_TIMESTAMP)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageTimestampOid, sizeof(extExtKeyUsageTimestampOid));
+ if (input & EXTKEYUSE_OCSP_SIGN)
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ extExtKeyUsageOcspSignOid, sizeof(extExtKeyUsageOcspSignOid));
+ #ifdef WOLFSSL_EKU_OID
+ /* iterate through OID values */
+ if (input & EXTKEYUSE_USER) {
+ int i, sz;
+ for (i = 0; i < CTC_MAX_EKU_NB; i++) {
+ sz = cert->extKeyUsageOIDSz[i];
+ if (sz > 0) {
+ ret |= SetOjectIdValue(output, outSz, &idx,
+ cert->extKeyUsageOID[i], sz);
+ }
+ }
+ }
+ #endif /* WOLFSSL_EKU_OID */
+ }
+ if (ret != 0)
+ return ASN_PARSE_E;
+
+ /* Calculate Sizes */
+ oidListSz = idx - totalSz;
+ totalSz = idx - 2; /* exclude first seq/len (2) */
+
+ /* 1. Seq + Total Len (2) */
+ idx = SetSequence(totalSz, output);
+
+ /* 2. Object ID (2) */
+ XMEMCPY(&output[idx], extkeyusage_oid, sizeof(extkeyusage_oid));
+ idx += sizeof(extkeyusage_oid);
+
+ /* 3. Octet String (2) */
+ idx += SetOctetString(totalSz - idx, &output[idx]);
+
+ /* 4. Seq + OidListLen (2) */
+ idx += SetSequence(oidListSz, &output[idx]);
+
+ /* 5. Oid List (already set in-place above) */
+ idx += oidListSz;
+
+ (void)cert;
+ return idx;
+}
+
+/* encode Certificate Policies, return total bytes written
+ * each input value must be ITU-T X.690 formatted : a.b.c...
+ * input must be an array of values with a NULL terminated for the latest
+ * RFC5280 : non-critical */
+static int SetCertificatePolicies(byte *output,
+ word32 outputSz,
+ char input[MAX_CERTPOL_NB][MAX_CERTPOL_SZ],
+ word16 nb_certpol,
+ void* heap)
+{
+ byte oid[MAX_OID_SZ],
+ der_oid[MAX_CERTPOL_NB][MAX_OID_SZ],
+ out[MAX_CERTPOL_SZ];
+ word32 oidSz;
+ word32 outSz, i = 0, der_oidSz[MAX_CERTPOL_NB];
+ int ret;
+
+ const byte certpol_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04 };
+ const byte oid_oid[] = { 0x06 };
+
+ if (output == NULL || input == NULL || nb_certpol > MAX_CERTPOL_NB)
+ return BAD_FUNC_ARG;
+
+ for (i = 0; i < nb_certpol; i++) {
+ oidSz = sizeof(oid);
+ XMEMSET(oid, 0, oidSz);
+
+ ret = EncodePolicyOID(oid, &oidSz, input[i], heap);
+ if (ret != 0)
+ return ret;
+
+ /* compute sequence value for the oid */
+ ret = SetOidValue(der_oid[i], MAX_OID_SZ, oid_oid,
+ sizeof(oid_oid), oid, oidSz);
+ if (ret <= 0)
+ return ret;
+ else
+ der_oidSz[i] = (word32)ret;
+ }
+
+ /* concatenate oid, keep two byte for sequence/size of the created value */
+ for (i = 0, outSz = 2; i < nb_certpol; i++) {
+ XMEMCPY(out+outSz, der_oid[i], der_oidSz[i]);
+ outSz += der_oidSz[i];
+ }
+
+ /* add sequence */
+ ret = SetSequence(outSz-2, out);
+ if (ret <= 0)
+ return ret;
+
+ /* add Policy OID to compute final value */
+ return SetOidValue(output, outputSz, certpol_oid, sizeof(certpol_oid),
+ out, outSz);
+}
+#endif /* WOLFSSL_CERT_EXT */
+
+
+#ifdef WOLFSSL_ALT_NAMES
+
+/* encode Alternative Names, return total bytes written */
+static int SetAltNames(byte *output, word32 outSz,
+ const byte *input, word32 length)
+{
+ byte san_len[1 + MAX_LENGTH_SZ];
+ int idx = 0, san_lenSz;
+ const byte san_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x11 };
+
+ if (output == NULL || input == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outSz < length)
+ return BUFFER_E;
+
+ /* Octet String header */
+ san_lenSz = SetOctetString(length, san_len);
+
+ if (outSz < MAX_SEQ_SZ)
+ return BUFFER_E;
+
+ idx = SetSequence(length + sizeof(san_oid) + san_lenSz, output);
+
+ if ((length + sizeof(san_oid) + san_lenSz) > outSz)
+ return BUFFER_E;
+
+ /* put oid */
+ XMEMCPY(output+idx, san_oid, sizeof(san_oid));
+ idx += sizeof(san_oid);
+
+ /* put octet header */
+ XMEMCPY(output+idx, san_len, san_lenSz);
+ idx += san_lenSz;
+
+ /* put value */
+ XMEMCPY(output+idx, input, length);
+ idx += length;
+
+ return idx;
+}
+
+
+#ifdef WOLFSSL_CERT_GEN
+
+int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names)
+{
+ word32 idx;
+ const DNS_entry* curName;
+ word32 namesSz = 0;
+
+ if (output == NULL)
+ return BAD_FUNC_ARG;
+
+ if (names == NULL)
+ return 0;
+
+ curName = names;
+ do {
+ namesSz += curName->len + 2 +
+ ((curName->len < ASN_LONG_LENGTH) ? 0
+ : BytePrecision(curName->len));
+ curName = curName->next;
+ } while (curName != NULL);
+
+ if (outputSz < MAX_SEQ_SZ + namesSz)
+ return BUFFER_E;
+
+ idx = SetSequence(namesSz, output);
+
+ curName = names;
+ do {
+ output[idx++] = ASN_CONTEXT_SPECIFIC | curName->type;
+ idx += SetLength(curName->len, output + idx);
+ XMEMCPY(output + idx, curName->name, curName->len);
+ idx += curName->len;
+ curName = curName->next;
+ } while (curName != NULL);
+
+ return idx;
+}
+
+#endif /* WOLFSSL_CERT_GEN */
+
+#endif /* WOLFSSL_ALT_NAMES */
+
+/* Encodes one attribute of the name (issuer/subject)
+ *
+ * name structure to hold result of encoding
+ * nameStr value to be encoded
+ * nameType type of encoding i.e CTC_UTF8
+ * type id of attribute i.e ASN_COMMON_NAME
+ *
+ * returns length on success
+ */
+static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType,
+ byte type)
+{
+ word32 idx = 0;
+
+ if (nameStr) {
+ /* bottom up */
+ byte firstLen[1 + MAX_LENGTH_SZ];
+ byte secondLen[MAX_LENGTH_SZ];
+ byte sequence[MAX_SEQ_SZ];
+ byte set[MAX_SET_SZ];
+
+ int strLen = (int)XSTRLEN(nameStr);
+ int thisLen = strLen;
+ int firstSz, secondSz, seqSz, setSz;
+
+ if (strLen == 0) { /* no user data for this item */
+ name->used = 0;
+ return 0;
+ }
+
+ /* Restrict country code size */
+ if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) {
+ return ASN_COUNTRY_SIZE_E;
+ }
+
+ secondSz = SetLength(strLen, secondLen);
+ thisLen += secondSz;
+ switch (type) {
+ case ASN_EMAIL_NAME: /* email */
+ thisLen += EMAIL_JOINT_LEN;
+ firstSz = EMAIL_JOINT_LEN;
+ break;
+
+ case ASN_DOMAIN_COMPONENT:
+ thisLen += PILOT_JOINT_LEN;
+ firstSz = PILOT_JOINT_LEN;
+ break;
+
+ default:
+ thisLen++; /* str type */
+ thisLen += JOINT_LEN;
+ firstSz = JOINT_LEN + 1;
+ }
+ thisLen++; /* id type */
+ firstSz = SetObjectId(firstSz, firstLen);
+ thisLen += firstSz;
+
+ seqSz = SetSequence(thisLen, sequence);
+ thisLen += seqSz;
+ setSz = SetSet(thisLen, set);
+ thisLen += setSz;
+
+ if (thisLen > (int)sizeof(name->encoded)) {
+ return BUFFER_E;
+ }
+
+ /* store it */
+ idx = 0;
+ /* set */
+ XMEMCPY(name->encoded, set, setSz);
+ idx += setSz;
+ /* seq */
+ XMEMCPY(name->encoded + idx, sequence, seqSz);
+ idx += seqSz;
+ /* asn object id */
+ XMEMCPY(name->encoded + idx, firstLen, firstSz);
+ idx += firstSz;
+ switch (type) {
+ case ASN_EMAIL_NAME:
+ {
+ const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x09, 0x01, 0x16 };
+ /* email joint id */
+ XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
+ idx += (int)sizeof(EMAIL_OID);
+ }
+ break;
+
+ case ASN_DOMAIN_COMPONENT:
+ {
+ const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89,
+ 0x93, 0xF2, 0x2C, 0x64, 0x01
+ };
+
+ XMEMCPY(name->encoded + idx, PILOT_OID,
+ sizeof(PILOT_OID));
+ idx += (int)sizeof(PILOT_OID);
+ /* id type */
+ name->encoded[idx++] = type;
+ /* str type */
+ name->encoded[idx++] = nameType;
+ }
+ break;
+
+ default:
+ name->encoded[idx++] = 0x55;
+ name->encoded[idx++] = 0x04;
+ /* id type */
+ name->encoded[idx++] = type;
+ /* str type */
+ name->encoded[idx++] = nameType;
+ }
+ /* second length */
+ XMEMCPY(name->encoded + idx, secondLen, secondSz);
+ idx += secondSz;
+ /* str value */
+ XMEMCPY(name->encoded + idx, nameStr, strLen);
+ idx += strLen;
+
+ name->type = type;
+ name->totalLen = idx;
+ name->used = 1;
+ }
+ else
+ name->used = 0;
+
+ return idx;
+}
+
/* encode CertName into output, return total bytes written */
-static int SetName(byte* output, CertName* name)
+int SetName(byte* output, word32 outputSz, CertName* name)
{
int totalBytes = 0, i, idx;
#ifdef WOLFSSL_SMALL_STACK
@@ -5447,6 +12679,16 @@ static int SetName(byte* output, CertName* name)
#else
EncodedName names[NAME_ENTRIES];
#endif
+#ifdef WOLFSSL_MULTI_ATTRIB
+ EncodedName addNames[CTC_MAX_ATTRIB];
+ int j, type;
+#endif
+
+ if (output == NULL || name == NULL)
+ return BAD_FUNC_ARG;
+
+ if (outputSz < 3)
+ return BUFFER_E;
#ifdef WOLFSSL_SMALL_STACK
names = (EncodedName*)XMALLOC(sizeof(EncodedName) * NAME_ENTRIES, NULL,
@@ -5456,96 +12698,38 @@ static int SetName(byte* output, CertName* name)
#endif
for (i = 0; i < NAME_ENTRIES; i++) {
+ int ret;
const char* nameStr = GetOneName(name, i);
- if (nameStr) {
- /* bottom up */
- byte firstLen[MAX_LENGTH_SZ];
- byte secondLen[MAX_LENGTH_SZ];
- byte sequence[MAX_SEQ_SZ];
- byte set[MAX_SET_SZ];
-
- int email = i == (NAME_ENTRIES - 1) ? 1 : 0;
- int strLen = (int)XSTRLEN(nameStr);
- int thisLen = strLen;
- int firstSz, secondSz, seqSz, setSz;
-
- if (strLen == 0) { /* no user data for this item */
- names[i].used = 0;
- continue;
- }
-
- secondSz = SetLength(strLen, secondLen);
- thisLen += secondSz;
- if (email) {
- thisLen += EMAIL_JOINT_LEN;
- thisLen ++; /* id type */
- firstSz = SetLength(EMAIL_JOINT_LEN, firstLen);
- }
- else {
- thisLen++; /* str type */
- thisLen++; /* id type */
- thisLen += JOINT_LEN;
- firstSz = SetLength(JOINT_LEN + 1, firstLen);
- }
- thisLen += firstSz;
- thisLen++; /* object id */
-
- seqSz = SetSequence(thisLen, sequence);
- thisLen += seqSz;
- setSz = SetSet(thisLen, set);
- thisLen += setSz;
- if (thisLen > (int)sizeof(names[i].encoded)) {
-#ifdef WOLFSSL_SMALL_STACK
+ ret = wc_EncodeName(&names[i], nameStr, GetNameType(name, i),
+ GetNameId(i));
+ if (ret < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ #endif
+ return BUFFER_E;
+ }
+ totalBytes += ret;
+ }
+#ifdef WOLFSSL_MULTI_ATTRIB
+ for (i = 0; i < CTC_MAX_ATTRIB; i++) {
+ if (name->name[i].sz > 0) {
+ int ret;
+ ret = wc_EncodeName(&addNames[i], name->name[i].value,
+ name->name[i].type, name->name[i].id);
+ if (ret < 0) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
return BUFFER_E;
}
-
- /* store it */
- idx = 0;
- /* set */
- XMEMCPY(names[i].encoded, set, setSz);
- idx += setSz;
- /* seq */
- XMEMCPY(names[i].encoded + idx, sequence, seqSz);
- idx += seqSz;
- /* asn object id */
- names[i].encoded[idx++] = ASN_OBJECT_ID;
- /* first length */
- XMEMCPY(names[i].encoded + idx, firstLen, firstSz);
- idx += firstSz;
- if (email) {
- const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x09, 0x01, 0x16 };
- /* email joint id */
- XMEMCPY(names[i].encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
- idx += (int)sizeof(EMAIL_OID);
- }
- else {
- /* joint id */
- byte bType = GetNameId(i);
- names[i].encoded[idx++] = 0x55;
- names[i].encoded[idx++] = 0x04;
- /* id type */
- names[i].encoded[idx++] = bType;
- /* str type */
- names[i].encoded[idx++] = GetNameType(name, i);
- }
- /* second length */
- XMEMCPY(names[i].encoded + idx, secondLen, secondSz);
- idx += secondSz;
- /* str value */
- XMEMCPY(names[i].encoded + idx, nameStr, strLen);
- idx += strLen;
-
- totalBytes += idx;
- names[i].totalLen = idx;
- names[i].used = 1;
+ totalBytes += ret;
+ }
+ else {
+ addNames[i].used = 0;
}
- else
- names[i].used = 0;
}
+#endif /* WOLFSSL_MULTI_ATTRIB */
/* header */
idx = SetSequence(totalBytes, output);
@@ -5558,7 +12742,54 @@ static int SetName(byte* output, CertName* name)
}
for (i = 0; i < NAME_ENTRIES; i++) {
+ #ifdef WOLFSSL_MULTI_ATTRIB
+ type = GetNameId(i);
+
+ /* list all DC values before OUs */
+ if (type == ASN_ORGUNIT_NAME) {
+ type = ASN_DOMAIN_COMPONENT;
+ for (j = 0; j < CTC_MAX_ATTRIB; j++) {
+ if (name->name[j].sz > 0 && type == name->name[j].id) {
+ if (outputSz < (word32)(idx+addNames[j].totalLen)) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(output + idx, addNames[j].encoded,
+ addNames[j].totalLen);
+ idx += addNames[j].totalLen;
+ }
+ }
+ type = ASN_ORGUNIT_NAME;
+ }
+
+ /* write all similar types to the buffer */
+ for (j = 0; j < CTC_MAX_ATTRIB; j++) {
+ if (name->name[j].sz > 0 && type == name->name[j].id) {
+ if (outputSz < (word32)(idx+addNames[j].totalLen)) {
+ #ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ #endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(output + idx, addNames[j].encoded,
+ addNames[j].totalLen);
+ idx += addNames[j].totalLen;
+ }
+ }
+ #endif /* WOLFSSL_MULTI_ATTRIB */
+
if (names[i].used) {
+ if (outputSz < (word32)(idx+names[i].totalLen)) {
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+ return BUFFER_E;
+ }
+
XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
idx += names[i].totalLen;
}
@@ -5573,13 +12804,19 @@ static int SetName(byte* output, CertName* name)
/* encode info from cert into DER encoded format */
static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
- RNG* rng, const byte* ntruKey, word16 ntruSz)
+ WC_RNG* rng, const byte* ntruKey, word16 ntruSz,
+ ed25519_key* ed25519Key, ed448_key* ed448Key)
{
int ret;
- (void)eccKey;
- (void)ntruKey;
- (void)ntruSz;
+ if (cert == NULL || der == NULL || rng == NULL)
+ return BAD_FUNC_ARG;
+
+ /* make sure at least one key type is provided */
+ if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
+ ed448Key == NULL && ntruKey == NULL) {
+ return PUBLIC_KEY_E;
+ }
/* init */
XMEMSET(der, 0, sizeof(DerCert));
@@ -5587,65 +12824,95 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
/* version */
der->versionSz = SetMyVersion(cert->version, der->version, TRUE);
- /* serial number */
- ret = wc_RNG_GenerateBlock(rng, cert->serial, CTC_SERIAL_SIZE);
- if (ret != 0)
- return ret;
-
- cert->serial[0] = 0x01; /* ensure positive */
- der->serialSz = SetSerial(cert->serial, der->serial);
+ /* serial number (must be positive) */
+ if (cert->serialSz == 0) {
+ /* generate random serial */
+ cert->serialSz = CTC_GEN_SERIAL_SZ;
+ ret = wc_RNG_GenerateBlock(rng, cert->serial, cert->serialSz);
+ if (ret != 0)
+ return ret;
+ /* Clear the top bit to avoid a negative value */
+ cert->serial[0] &= 0x7f;
+ }
+ der->serialSz = SetSerialNumber(cert->serial, cert->serialSz, der->serial,
+ sizeof(der->serial), CTC_SERIAL_SIZE);
+ if (der->serialSz < 0)
+ return der->serialSz;
/* signature algo */
- der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, sigType, 0);
- if (der->sigAlgoSz == 0)
+ der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, oidSigType, 0);
+ if (der->sigAlgoSz <= 0)
return ALGO_ID_E;
/* public key */
+#ifndef NO_RSA
if (cert->keyType == RSA_KEY) {
if (rsaKey == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey);
- if (der->publicKeySz <= 0)
- return PUBLIC_KEY_E;
+ der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
+ sizeof(der->publicKey), 1);
}
+#endif
#ifdef HAVE_ECC
if (cert->keyType == ECC_KEY) {
if (eccKey == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey);
- if (der->publicKeySz <= 0)
+ der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
+ }
+#endif
+
+#ifdef HAVE_ED25519
+ if (cert->keyType == ED25519_KEY) {
+ if (ed25519Key == NULL)
return PUBLIC_KEY_E;
+ der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
}
-#endif /* HAVE_ECC */
+#endif
+
+#ifdef HAVE_ED448
+ if (cert->keyType == ED448_KEY) {
+ if (ed448Key == NULL)
+ return PUBLIC_KEY_E;
+ der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 1);
+ }
+#endif
#ifdef HAVE_NTRU
if (cert->keyType == NTRU_KEY) {
word32 rc;
word16 encodedSz;
- rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
+ if (ntruKey == NULL)
+ return PUBLIC_KEY_E;
+
+ rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
ntruKey, &encodedSz, NULL);
if (rc != NTRU_OK)
return PUBLIC_KEY_E;
if (encodedSz > MAX_PUBLIC_KEY_SZ)
return PUBLIC_KEY_E;
- rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( ntruSz,
+ rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz,
ntruKey, &encodedSz, der->publicKey);
if (rc != NTRU_OK)
return PUBLIC_KEY_E;
der->publicKeySz = encodedSz;
}
+#else
+ (void)ntruSz;
#endif /* HAVE_NTRU */
+ if (der->publicKeySz <= 0)
+ return PUBLIC_KEY_E;
+
der->validitySz = 0;
#ifdef WOLFSSL_ALT_NAMES
/* date validity copy ? */
if (cert->beforeDateSz && cert->afterDateSz) {
der->validitySz = CopyValidity(der->validity, cert);
- if (der->validitySz == 0)
+ if (der->validitySz <= 0)
return DATE_E;
}
#endif
@@ -5653,49 +12920,247 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
/* date validity */
if (der->validitySz == 0) {
der->validitySz = SetValidity(der->validity, cert->daysValid);
- if (der->validitySz == 0)
+ if (der->validitySz <= 0)
return DATE_E;
}
/* subject name */
- der->subjectSz = SetName(der->subject, &cert->subject);
- if (der->subjectSz == 0)
+#ifdef WOLFSSL_CERT_EXT
+ if (XSTRLEN((const char*)cert->sbjRaw) > 0) {
+ /* Use the raw subject */
+ int idx;
+
+ der->subjectSz = min(sizeof(der->subject),
+ (word32)XSTRLEN((const char*)cert->sbjRaw));
+ /* header */
+ idx = SetSequence(der->subjectSz, der->subject);
+ if (der->subjectSz + idx > (int)sizeof(der->subject)) {
+ return SUBJECT_E;
+ }
+
+ XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw,
+ der->subjectSz);
+ der->subjectSz += idx;
+ }
+ else
+#endif
+ {
+ /* Use the name structure */
+ der->subjectSz = SetName(der->subject, sizeof(der->subject),
+ &cert->subject);
+ }
+ if (der->subjectSz <= 0)
return SUBJECT_E;
/* issuer name */
- der->issuerSz = SetName(der->issuer, cert->selfSigned ?
- &cert->subject : &cert->issuer);
- if (der->issuerSz == 0)
+#ifdef WOLFSSL_CERT_EXT
+ if (XSTRLEN((const char*)cert->issRaw) > 0) {
+ /* Use the raw issuer */
+ int idx;
+
+ der->issuerSz = min(sizeof(der->issuer),
+ (word32)XSTRLEN((const char*)cert->issRaw));
+ /* header */
+ idx = SetSequence(der->issuerSz, der->issuer);
+ if (der->issuerSz + idx > (int)sizeof(der->issuer)) {
+ return ISSUER_E;
+ }
+
+ XMEMCPY((char*)der->issuer + idx, (const char*)cert->issRaw,
+ der->issuerSz);
+ der->issuerSz += idx;
+ }
+ else
+#endif
+ {
+ /* Use the name structure */
+ der->issuerSz = SetName(der->issuer, sizeof(der->issuer),
+ cert->selfSigned ? &cert->subject : &cert->issuer);
+ }
+ if (der->issuerSz <= 0)
return ISSUER_E;
+ /* set the extensions */
+ der->extensionsSz = 0;
+
/* CA */
if (cert->isCA) {
- der->caSz = SetCa(der->ca);
- if (der->caSz == 0)
+ der->caSz = SetCa(der->ca, sizeof(der->ca));
+ if (der->caSz <= 0)
return CA_TRUE_E;
+
+ der->extensionsSz += der->caSz;
}
else
der->caSz = 0;
- /* extensions, just CA now */
- if (cert->isCA) {
- der->extensionsSz = SetExtensions(der->extensions,
- der->ca, der->caSz, TRUE);
- if (der->extensionsSz == 0)
- return EXTENSIONS_E;
+#ifdef WOLFSSL_ALT_NAMES
+ /* Alternative Name */
+ if (cert->altNamesSz) {
+ der->altNamesSz = SetAltNames(der->altNames, sizeof(der->altNames),
+ cert->altNames, cert->altNamesSz);
+ if (der->altNamesSz <= 0)
+ return ALT_NAME_E;
+
+ der->extensionsSz += der->altNamesSz;
}
else
- der->extensionsSz = 0;
+ der->altNamesSz = 0;
+#endif
-#ifdef WOLFSSL_ALT_NAMES
- if (der->extensionsSz == 0 && cert->altNamesSz) {
- der->extensionsSz = SetExtensions(der->extensions, cert->altNames,
- cert->altNamesSz, TRUE);
- if (der->extensionsSz == 0)
- return EXTENSIONS_E;
+#ifdef WOLFSSL_CERT_EXT
+ /* SKID */
+ if (cert->skidSz) {
+ /* check the provided SKID size */
+ if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
+ return SKID_E;
+
+ /* Note: different skid buffers sizes for der (MAX_KID_SZ) and
+ cert (CTC_MAX_SKID_SIZE). */
+ der->skidSz = SetSKID(der->skid, sizeof(der->skid),
+ cert->skid, cert->skidSz);
+ if (der->skidSz <= 0)
+ return SKID_E;
+
+ der->extensionsSz += der->skidSz;
+ }
+ else
+ der->skidSz = 0;
+
+ /* AKID */
+ if (cert->akidSz) {
+ /* check the provided AKID size */
+ if (cert->akidSz > (int)min(CTC_MAX_AKID_SIZE, sizeof(der->akid)))
+ return AKID_E;
+
+ der->akidSz = SetAKID(der->akid, sizeof(der->akid),
+ cert->akid, cert->akidSz, cert->heap);
+ if (der->akidSz <= 0)
+ return AKID_E;
+
+ der->extensionsSz += der->akidSz;
+ }
+ else
+ der->akidSz = 0;
+
+ /* Key Usage */
+ if (cert->keyUsage != 0){
+ der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
+ cert->keyUsage);
+ if (der->keyUsageSz <= 0)
+ return KEYUSAGE_E;
+
+ der->extensionsSz += der->keyUsageSz;
+ }
+ else
+ der->keyUsageSz = 0;
+
+ /* Extended Key Usage */
+ if (cert->extKeyUsage != 0){
+ der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
+ sizeof(der->extKeyUsage), cert->extKeyUsage);
+ if (der->extKeyUsageSz <= 0)
+ return EXTKEYUSAGE_E;
+
+ der->extensionsSz += der->extKeyUsageSz;
+ }
+ else
+ der->extKeyUsageSz = 0;
+
+ /* Certificate Policies */
+ if (cert->certPoliciesNb != 0) {
+ der->certPoliciesSz = SetCertificatePolicies(der->certPolicies,
+ sizeof(der->certPolicies),
+ cert->certPolicies,
+ cert->certPoliciesNb,
+ cert->heap);
+ if (der->certPoliciesSz <= 0)
+ return CERTPOLICIES_E;
+
+ der->extensionsSz += der->certPoliciesSz;
}
+ else
+ der->certPoliciesSz = 0;
+#endif /* WOLFSSL_CERT_EXT */
+
+ /* put extensions */
+ if (der->extensionsSz > 0) {
+
+ /* put the start of extensions sequence (ID, Size) */
+ der->extensionsSz = SetExtensionsHeader(der->extensions,
+ sizeof(der->extensions),
+ der->extensionsSz);
+ if (der->extensionsSz <= 0)
+ return EXTENSIONS_E;
+
+ /* put CA */
+ if (der->caSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->ca, der->caSz);
+ if (ret == 0)
+ return EXTENSIONS_E;
+ }
+
+#ifdef WOLFSSL_ALT_NAMES
+ /* put Alternative Names */
+ if (der->altNamesSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->altNames, der->altNamesSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
#endif
+#ifdef WOLFSSL_CERT_EXT
+ /* put SKID */
+ if (der->skidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->skid, der->skidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put AKID */
+ if (der->akidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->akid, der->akidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put KeyUsage */
+ if (der->keyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->keyUsage, der->keyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put ExtendedKeyUsage */
+ if (der->extKeyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->extKeyUsage, der->extKeyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put Certificate Policies */
+ if (der->certPoliciesSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->certPolicies, der->certPoliciesSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+#endif /* WOLFSSL_CERT_EXT */
+ }
+
der->total = der->versionSz + der->serialSz + der->sigAlgoSz +
der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz +
der->extensionsSz;
@@ -5705,37 +13170,37 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
/* write DER encoded cert to buffer, size already checked */
-static int WriteCertBody(DerCert* der, byte* buffer)
+static int WriteCertBody(DerCert* der, byte* buf)
{
int idx;
/* signed part header */
- idx = SetSequence(der->total, buffer);
+ idx = SetSequence(der->total, buf);
/* version */
- XMEMCPY(buffer + idx, der->version, der->versionSz);
+ XMEMCPY(buf + idx, der->version, der->versionSz);
idx += der->versionSz;
/* serial */
- XMEMCPY(buffer + idx, der->serial, der->serialSz);
+ XMEMCPY(buf + idx, der->serial, der->serialSz);
idx += der->serialSz;
/* sig algo */
- XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz);
+ XMEMCPY(buf + idx, der->sigAlgo, der->sigAlgoSz);
idx += der->sigAlgoSz;
/* issuer */
- XMEMCPY(buffer + idx, der->issuer, der->issuerSz);
+ XMEMCPY(buf + idx, der->issuer, der->issuerSz);
idx += der->issuerSz;
/* validity */
- XMEMCPY(buffer + idx, der->validity, der->validitySz);
+ XMEMCPY(buf + idx, der->validity, der->validitySz);
idx += der->validitySz;
/* subject */
- XMEMCPY(buffer + idx, der->subject, der->subjectSz);
+ XMEMCPY(buf + idx, der->subject, der->subjectSz);
idx += der->subjectSz;
/* public key */
- XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
+ XMEMCPY(buf + idx, der->publicKey, der->publicKeySz);
idx += der->publicKeySz;
if (der->extensionsSz) {
/* extensions */
- XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
- sizeof(der->extensions)));
+ XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz,
+ (int)sizeof(der->extensions)));
idx += der->extensionsSz;
}
@@ -5744,97 +13209,126 @@ static int WriteCertBody(DerCert* der, byte* buffer)
/* Make RSA signature from buffer (sz), write to sig (sigSz) */
-static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz,
- RsaKey* rsaKey, ecc_key* eccKey, RNG* rng,
- int sigAlgoType)
+static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, int sz,
+ byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey,
+ ed25519_key* ed25519Key, ed448_key* ed448Key, WC_RNG* rng, int sigAlgoType,
+ void* heap)
{
- int encSigSz, digestSz, typeH = 0, ret = 0;
- byte digest[SHA256_DIGEST_SIZE]; /* max size */
-#ifdef WOLFSSL_SMALL_STACK
- byte* encSig;
-#else
- byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ];
-#endif
+ int digestSz = 0, typeH = 0, ret = 0;
- (void)digest;
(void)digestSz;
- (void)encSig;
- (void)encSigSz;
(void)typeH;
-
- (void)buffer;
+ (void)buf;
(void)sz;
(void)sig;
(void)sigSz;
(void)rsaKey;
(void)eccKey;
+ (void)ed25519Key;
+ (void)ed448Key;
(void)rng;
+ (void)heap;
- switch (sigAlgoType) {
- #ifndef NO_MD5
- case CTC_MD5wRSA:
- if ((ret = wc_Md5Hash(buffer, sz, digest)) == 0) {
- typeH = MD5h;
- digestSz = MD5_DIGEST_SIZE;
+ switch (certSignCtx->state) {
+ case CERTSIGN_STATE_BEGIN:
+ case CERTSIGN_STATE_DIGEST:
+
+ certSignCtx->state = CERTSIGN_STATE_DIGEST;
+ certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (certSignCtx->digest == NULL) {
+ ret = MEMORY_E; goto exit_ms;
}
- break;
- #endif
- #ifndef NO_SHA
- case CTC_SHAwRSA:
- case CTC_SHAwECDSA:
- if ((ret = wc_ShaHash(buffer, sz, digest)) == 0) {
- typeH = SHAh;
- digestSz = SHA_DIGEST_SIZE;
+
+ ret = HashForSignature(buf, sz, sigAlgoType, certSignCtx->digest,
+ &typeH, &digestSz, 0);
+ /* set next state, since WC_PENDING_E rentry for these are not "call again" */
+ certSignCtx->state = CERTSIGN_STATE_ENCODE;
+ if (ret != 0) {
+ goto exit_ms;
}
- break;
- #endif
- #ifndef NO_SHA256
- case CTC_SHA256wRSA:
- case CTC_SHA256wECDSA:
- if ((ret = wc_Sha256Hash(buffer, sz, digest)) == 0) {
- typeH = SHA256h;
- digestSz = SHA256_DIGEST_SIZE;
+ FALL_THROUGH;
+
+ case CERTSIGN_STATE_ENCODE:
+ #ifndef NO_RSA
+ if (rsaKey) {
+ certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (certSignCtx->encSig == NULL) {
+ ret = MEMORY_E; goto exit_ms;
+ }
+
+ /* signature */
+ certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig,
+ certSignCtx->digest, digestSz, typeH);
}
+ #endif /* !NO_RSA */
+ FALL_THROUGH;
+
+ case CERTSIGN_STATE_DO:
+ certSignCtx->state = CERTSIGN_STATE_DO;
+ ret = ALGO_ID_E; /* default to error */
+
+ #ifndef NO_RSA
+ if (rsaKey) {
+ /* signature */
+ ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz,
+ sig, sigSz, rsaKey, rng);
+ }
+ #endif /* !NO_RSA */
+
+ #ifdef HAVE_ECC
+ if (!rsaKey && eccKey) {
+ word32 outSz = sigSz;
+
+ ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz,
+ sig, &outSz, rng, eccKey);
+ if (ret == 0)
+ ret = outSz;
+ }
+ #endif /* HAVE_ECC */
+
+ #ifdef HAVE_ED25519
+ if (!rsaKey && !eccKey && ed25519Key) {
+ word32 outSz = sigSz;
+
+ ret = wc_ed25519_sign_msg(buf, sz, sig, &outSz, ed25519Key);
+ if (ret == 0)
+ ret = outSz;
+ }
+ #endif /* HAVE_ECC */
+
+ #ifdef HAVE_ED448
+ if (!rsaKey && !eccKey && !ed25519Key && ed448Key) {
+ word32 outSz = sigSz;
+
+ ret = wc_ed448_sign_msg(buf, sz, sig, &outSz, ed448Key, NULL, 0);
+ if (ret == 0)
+ ret = outSz;
+ }
+ #endif /* HAVE_ECC */
break;
- #endif
- default:
- WOLFSSL_MSG("MakeSignautre called with unsupported type");
- ret = ALGO_ID_E;
}
-
- if (ret != 0)
+
+exit_ms:
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (ret == WC_PENDING_E) {
return ret;
-
-#ifdef WOLFSSL_SMALL_STACK
- encSig = (byte*)XMALLOC(MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ,
- NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (encSig == NULL)
- return MEMORY_E;
+ }
#endif
-
- ret = ALGO_ID_E;
-
+
#ifndef NO_RSA
if (rsaKey) {
- /* signature */
- encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH);
- ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng);
+ XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER);
}
-#endif
-
-#ifdef HAVE_ECC
- if (!rsaKey && eccKey) {
- word32 outSz = sigSz;
- ret = wc_ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey);
+#endif /* !NO_RSA */
- if (ret == 0)
- ret = outSz;
- }
-#endif
+ XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ certSignCtx->digest = NULL;
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+ /* reset state */
+ certSignCtx->state = CERTSIGN_STATE_BEGIN;
return ret;
}
@@ -5842,27 +13336,27 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz,
/* add signature to end of buffer, size of buffer assumed checked, return
new length */
-static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
+static int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
int sigAlgoType)
{
byte seq[MAX_SEQ_SZ];
int idx = bodySz, seqSz;
/* algo */
- idx += SetAlgoID(sigAlgoType, buffer + idx, sigType, 0);
+ idx += SetAlgoID(sigAlgoType, buf ? buf + idx : NULL, oidSigType, 0);
/* bit string */
- buffer[idx++] = ASN_BIT_STRING;
- /* length */
- idx += SetLength(sigSz + 1, buffer + idx);
- buffer[idx++] = 0; /* trailing 0 */
+ idx += SetBitString(sigSz, 0, buf ? buf + idx : NULL);
/* signature */
- XMEMCPY(buffer + idx, sig, sigSz);
+ if (buf)
+ XMEMCPY(buf + idx, sig, sigSz);
idx += sigSz;
/* make room for overall header */
seqSz = SetSequence(idx, seq);
- XMEMMOVE(buffer + seqSz, buffer, idx);
- XMEMCPY(buffer, seq, seqSz);
+ if (buf) {
+ XMEMMOVE(buf + seqSz, buf, idx);
+ XMEMCPY(buf, seq, seqSz);
+ }
return idx + seqSz;
}
@@ -5870,8 +13364,9 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz,
/* Make an x509 Certificate v3 any key type from cert input, write to buffer */
static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
- RsaKey* rsaKey, ecc_key* eccKey, RNG* rng,
- const byte* ntruKey, word16 ntruSz)
+ RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng,
+ const byte* ntruKey, word16 ntruSz,
+ ed25519_key* ed25519Key, ed448_key* ed448Key)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
@@ -5880,16 +13375,21 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
DerCert der[1];
#endif
- cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY);
+ if (derBuffer == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY :
+ (ed25519Key ? ED25519_KEY : (ed448Key ? ED448_KEY : NTRU_KEY)));
#ifdef WOLFSSL_SMALL_STACK
- der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (der == NULL)
return MEMORY_E;
#endif
- ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz);
-
+ ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz,
+ ed25519Key, ed448Key);
if (ret == 0) {
if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
ret = BUFFER_E;
@@ -5898,7 +13398,7 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
@@ -5906,19 +13406,41 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
+int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
+ void* key, WC_RNG* rng)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
+ ed25519Key, ed448Key);
+}
+/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,
- ecc_key* eccKey, RNG* rng)
+ ecc_key* eccKey, WC_RNG* rng)
{
- return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0);
+ return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
+ NULL, NULL);
}
#ifdef HAVE_NTRU
int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
- const byte* ntruKey, word16 keySz, RNG* rng)
+ const byte* ntruKey, word16 keySz, WC_RNG* rng)
{
- return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz);
+ return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz, NULL);
}
#endif /* HAVE_NTRU */
@@ -5926,12 +13448,13 @@ int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
#ifdef WOLFSSL_CERT_REQ
-static int SetReqAttrib(byte* output, char* pw, int extSz)
+static int SetReqAttrib(byte* output, char* pw, int pwPrintableString,
+ int extSz)
{
- static const byte cpOid[] =
+ const byte cpOid[] =
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x09, 0x07 };
- static const byte erOid[] =
+ const byte erOid[] =
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x09, 0x0e };
@@ -5955,7 +13478,11 @@ static int SetReqAttrib(byte* output, char* pw, int extSz)
if (pw && pw[0]) {
pwSz = (int)XSTRLEN(pw);
- cpStrSz = SetUTF8String(pwSz, cpStr);
+ if (pwPrintableString) {
+ cpStrSz = SetPrintableString(pwSz, cpStr);
+ } else {
+ cpStrSz = SetUTF8String(pwSz, cpStr);
+ }
cpSetSz = SetSet(cpStrSz + pwSz, cpSet);
cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq);
cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz;
@@ -5998,10 +13525,21 @@ static int SetReqAttrib(byte* output, char* pw, int extSz)
/* encode info from cert into DER encoded format */
-static int EncodeCertReq(Cert* cert, DerCert* der,
- RsaKey* rsaKey, ecc_key* eccKey)
+static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
+ ecc_key* eccKey, ed25519_key* ed25519Key,
+ ed448_key* ed448Key)
{
(void)eccKey;
+ (void)ed25519Key;
+ (void)ed448Key;
+
+ if (cert == NULL || der == NULL)
+ return BAD_FUNC_ARG;
+
+ if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
+ ed448Key == NULL) {
+ return PUBLIC_KEY_E;
+ }
/* init */
XMEMSET(der, 0, sizeof(DerCert));
@@ -6010,51 +13548,163 @@ static int EncodeCertReq(Cert* cert, DerCert* der,
der->versionSz = SetMyVersion(cert->version, der->version, FALSE);
/* subject name */
- der->subjectSz = SetName(der->subject, &cert->subject);
- if (der->subjectSz == 0)
+ der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject);
+ if (der->subjectSz <= 0)
return SUBJECT_E;
/* public key */
+#ifndef NO_RSA
if (cert->keyType == RSA_KEY) {
if (rsaKey == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey);
- if (der->publicKeySz <= 0)
- return PUBLIC_KEY_E;
+ der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey,
+ sizeof(der->publicKey), 1);
}
+#endif
#ifdef HAVE_ECC
if (cert->keyType == ECC_KEY) {
- if (eccKey == NULL)
+ der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
+ }
+#endif
+
+#ifdef HAVE_ED25519
+ if (cert->keyType == ED25519_KEY) {
+ if (ed25519Key == NULL)
return PUBLIC_KEY_E;
- der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey);
- if (der->publicKeySz <= 0)
+ der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1);
+ }
+#endif
+
+#ifdef HAVE_ED448
+ if (cert->keyType == ED448_KEY) {
+ if (ed448Key == NULL)
return PUBLIC_KEY_E;
+ der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, 1);
}
-#endif /* HAVE_ECC */
+#endif
+ if (der->publicKeySz <= 0)
+ return PUBLIC_KEY_E;
+
+ /* set the extensions */
+ der->extensionsSz = 0;
/* CA */
if (cert->isCA) {
- der->caSz = SetCa(der->ca);
- if (der->caSz == 0)
+ der->caSz = SetCa(der->ca, sizeof(der->ca));
+ if (der->caSz <= 0)
return CA_TRUE_E;
+
+ der->extensionsSz += der->caSz;
}
else
der->caSz = 0;
- /* extensions, just CA now */
- if (cert->isCA) {
- der->extensionsSz = SetExtensions(der->extensions,
- der->ca, der->caSz, FALSE);
- if (der->extensionsSz == 0)
- return EXTENSIONS_E;
+#ifdef WOLFSSL_CERT_EXT
+ /* SKID */
+ if (cert->skidSz) {
+ /* check the provided SKID size */
+ if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid)))
+ return SKID_E;
+
+ der->skidSz = SetSKID(der->skid, sizeof(der->skid),
+ cert->skid, cert->skidSz);
+ if (der->skidSz <= 0)
+ return SKID_E;
+
+ der->extensionsSz += der->skidSz;
+ }
+ else
+ der->skidSz = 0;
+
+ /* Key Usage */
+ if (cert->keyUsage != 0){
+ der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage),
+ cert->keyUsage);
+ if (der->keyUsageSz <= 0)
+ return KEYUSAGE_E;
+
+ der->extensionsSz += der->keyUsageSz;
}
else
- der->extensionsSz = 0;
+ der->keyUsageSz = 0;
- der->attribSz = SetReqAttrib(der->attrib,
- cert->challengePw, der->extensionsSz);
- if (der->attribSz == 0)
+ /* Extended Key Usage */
+ if (cert->extKeyUsage != 0){
+ der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage,
+ sizeof(der->extKeyUsage), cert->extKeyUsage);
+ if (der->extKeyUsageSz <= 0)
+ return EXTKEYUSAGE_E;
+
+ der->extensionsSz += der->extKeyUsageSz;
+ }
+ else
+ der->extKeyUsageSz = 0;
+
+#endif /* WOLFSSL_CERT_EXT */
+
+ /* put extensions */
+ if (der->extensionsSz > 0) {
+ int ret;
+
+ /* put the start of sequence (ID, Size) */
+ der->extensionsSz = SetSequence(der->extensionsSz, der->extensions);
+ if (der->extensionsSz <= 0)
+ return EXTENSIONS_E;
+
+ /* put CA */
+ if (der->caSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->ca, der->caSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+#ifdef WOLFSSL_CERT_EXT
+ /* put SKID */
+ if (der->skidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->skid, der->skidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put AKID */
+ if (der->akidSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->akid, der->akidSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put KeyUsage */
+ if (der->keyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->keyUsage, der->keyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+ /* put ExtendedKeyUsage */
+ if (der->extKeyUsageSz) {
+ ret = SetExtensions(der->extensions, sizeof(der->extensions),
+ &der->extensionsSz,
+ der->extKeyUsage, der->extKeyUsageSz);
+ if (ret <= 0)
+ return EXTENSIONS_E;
+ }
+
+#endif /* WOLFSSL_CERT_EXT */
+ }
+
+ der->attribSz = SetReqAttrib(der->attrib, cert->challengePw,
+ cert->challengePwPrintableString,
+ der->extensionsSz);
+ if (der->attribSz <= 0)
return REQ_ATTRIBUTE_E;
der->total = der->versionSz + der->subjectSz + der->publicKeySz +
@@ -6065,28 +13715,33 @@ static int EncodeCertReq(Cert* cert, DerCert* der,
/* write DER encoded cert req to buffer, size already checked */
-static int WriteCertReqBody(DerCert* der, byte* buffer)
+static int WriteCertReqBody(DerCert* der, byte* buf)
{
int idx;
/* signed part header */
- idx = SetSequence(der->total, buffer);
+ idx = SetSequence(der->total, buf);
/* version */
- XMEMCPY(buffer + idx, der->version, der->versionSz);
+ if (buf)
+ XMEMCPY(buf + idx, der->version, der->versionSz);
idx += der->versionSz;
/* subject */
- XMEMCPY(buffer + idx, der->subject, der->subjectSz);
+ if (buf)
+ XMEMCPY(buf + idx, der->subject, der->subjectSz);
idx += der->subjectSz;
/* public key */
- XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz);
+ if (buf)
+ XMEMCPY(buf + idx, der->publicKey, der->publicKeySz);
idx += der->publicKeySz;
/* attributes */
- XMEMCPY(buffer + idx, der->attrib, der->attribSz);
+ if (buf)
+ XMEMCPY(buf + idx, der->attrib, der->attribSz);
idx += der->attribSz;
/* extensions */
if (der->extensionsSz) {
- XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz,
- sizeof(der->extensions)));
+ if (buf)
+ XMEMCPY(buf + idx, der->extensions, min(der->extensionsSz,
+ (int)sizeof(der->extensions)));
idx += der->extensionsSz;
}
@@ -6094,8 +13749,9 @@ static int WriteCertReqBody(DerCert* der, byte* buffer)
}
-int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
- RsaKey* rsaKey, ecc_key* eccKey)
+static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
+ RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
+ ed448_key* ed448Key)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
@@ -6104,15 +13760,17 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
DerCert der[1];
#endif
- cert->keyType = eccKey ? ECC_KEY : RSA_KEY;
+ cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY :
+ (ed448Key ? ED448_KEY: RSA_KEY));
#ifdef WOLFSSL_SMALL_STACK
- der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
if (der == NULL)
return MEMORY_E;
#endif
- ret = EncodeCertReq(cert, der, rsaKey, eccKey);
+ ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key, ed448Key);
if (ret == 0) {
if (der->total + MAX_SEQ_SZ * 2 > (int)derSz)
@@ -6122,100 +13780,669 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
}
#ifdef WOLFSSL_SMALL_STACK
- XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
+int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType,
+ void* key)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key,
+ ed448Key);
+}
+
+int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
+ RsaKey* rsaKey, ecc_key* eccKey)
+{
+ return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL, NULL);
+}
#endif /* WOLFSSL_CERT_REQ */
-int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz,
- RsaKey* rsaKey, ecc_key* eccKey, RNG* rng)
+static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
+ RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
+ ed448_key* ed448Key, WC_RNG* rng)
{
- int sigSz;
-#ifdef WOLFSSL_SMALL_STACK
- byte* sig;
+ int sigSz = 0;
+ void* heap = NULL;
+ CertSignCtx* certSignCtx;
+#ifndef WOLFSSL_ASYNC_CRYPT
+ CertSignCtx certSignCtx_lcl;
+
+ certSignCtx = &certSignCtx_lcl;
+ XMEMSET(certSignCtx, 0, sizeof(CertSignCtx));
#else
- byte sig[MAX_ENCODED_SIG_SZ];
+ certSignCtx = NULL;
#endif
if (requestSz < 0)
return requestSz;
-#ifdef WOLFSSL_SMALL_STACK
- sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (sig == NULL)
- return MEMORY_E;
+ /* locate ctx */
+ if (rsaKey) {
+ #ifndef NO_RSA
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ certSignCtx = &rsaKey->certSignCtx;
+ #endif
+ heap = rsaKey->heap;
+ #else
+ return NOT_COMPILED_IN;
+ #endif /* NO_RSA */
+ }
+ else if (eccKey) {
+ #ifdef HAVE_ECC
+ #ifdef WOLFSSL_ASYNC_CRYPT
+ certSignCtx = &eccKey->certSignCtx;
+ #endif
+ heap = eccKey->heap;
+ #else
+ return NOT_COMPILED_IN;
+ #endif /* HAVE_ECC */
+ }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (certSignCtx == NULL) {
+ return BAD_FUNC_ARG;
+ }
#endif
- sigSz = MakeSignature(buffer, requestSz, sig, MAX_ENCODED_SIG_SZ, rsaKey,
- eccKey, rng, sType);
+ if (certSignCtx->sig == NULL) {
+ certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (certSignCtx->sig == NULL)
+ return MEMORY_E;
+ }
+
+ sigSz = MakeSignature(certSignCtx, buf, requestSz, certSignCtx->sig,
+ MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, rng, sType,
+ heap);
+#ifdef WOLFSSL_ASYNC_CRYPT
+ if (sigSz == WC_PENDING_E) {
+ /* Not free'ing certSignCtx->sig here because it could still be in use
+ * with async operations. */
+ return sigSz;
+ }
+#endif
if (sigSz >= 0) {
if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz)
sigSz = BUFFER_E;
else
- sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType);
+ sigSz = AddSignature(buf, requestSz, certSignCtx->sig, sigSz,
+ sType);
}
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
+
+ XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ certSignCtx->sig = NULL;
return sigSz;
}
+int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz,
+ int keyType, void* key, WC_RNG* rng)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, ed25519Key,
+ ed448Key, rng);
+}
+
+int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
+ RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng)
+{
+ return SignCert(requestSz, sType, buf, buffSz, rsaKey, eccKey, NULL, NULL,
+ rng);
+}
-int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, RNG* rng)
+int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz,
+ RsaKey* key, WC_RNG* rng)
{
- int ret = wc_MakeCert(cert, buffer, buffSz, key, NULL, rng);
+ int ret;
+ ret = wc_MakeCert(cert, buf, buffSz, key, NULL, rng);
if (ret < 0)
return ret;
- return wc_SignCert(cert->bodySz, cert->sigType, buffer, buffSz, key, NULL,rng);
+ return wc_SignCert(cert->bodySz, cert->sigType,
+ buf, buffSz, key, NULL, rng);
}
-#ifdef WOLFSSL_ALT_NAMES
+#ifdef WOLFSSL_CERT_EXT
-/* Set Alt Names from der cert, return 0 on success */
-static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
+/* Get raw subject from cert, which may contain OIDs not parsed by Decode.
+ The raw subject pointer will only be valid while "cert" is valid. */
+int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert)
{
- int ret;
-#ifdef WOLFSSL_SMALL_STACK
- DecodedCert* decoded;
+ int rc = BAD_FUNC_ARG;
+ if ((subjectRaw != NULL) && (cert != NULL)) {
+ *subjectRaw = cert->sbjRaw;
+ rc = 0;
+ }
+ return rc;
+}
+
+/* Set KID from public key */
+static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey,
+ byte *ntruKey, word16 ntruKeySz,
+ ed25519_key* ed25519Key, ed448_key* ed448Key,
+ int kid_type)
+{
+ byte *buf;
+ int bufferSz, ret;
+
+ if (cert == NULL ||
+ (rsakey == NULL && eckey == NULL && ntruKey == NULL &&
+ ed25519Key == NULL && ed448Key == NULL) ||
+ (kid_type != SKID_TYPE && kid_type != AKID_TYPE))
+ return BAD_FUNC_ARG;
+
+ buf = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (buf == NULL)
+ return MEMORY_E;
+
+ /* Public Key */
+ bufferSz = -1;
+#ifndef NO_RSA
+ /* RSA public key */
+ if (rsakey != NULL)
+ bufferSz = SetRsaPublicKey(buf, rsakey, MAX_PUBLIC_KEY_SZ, 0);
+#endif
+#ifdef HAVE_ECC
+ /* ECC public key */
+ if (eckey != NULL)
+ bufferSz = SetEccPublicKey(buf, eckey, 0);
+#endif
+#ifdef HAVE_NTRU
+ /* NTRU public key */
+ if (ntruKey != NULL) {
+ bufferSz = MAX_PUBLIC_KEY_SZ;
+ ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
+ ntruKeySz, ntruKey, (word16 *)(&bufferSz), buf);
+ if (ret != NTRU_OK)
+ bufferSz = -1;
+ }
#else
- DecodedCert decoded[1];
+ (void)ntruKeySz;
+#endif
+#ifdef HAVE_ED25519
+ /* ED25519 public key */
+ if (ed25519Key != NULL)
+ bufferSz = SetEd25519PublicKey(buf, ed25519Key, 0);
+#endif
+#ifdef HAVE_ED448
+ /* ED448 public key */
+ if (ed448Key != NULL)
+ bufferSz = SetEd448PublicKey(buffer, ed448Key, 0);
#endif
- if (derSz < 0)
+ if (bufferSz <= 0) {
+ XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return PUBLIC_KEY_E;
+ }
+
+ /* Compute SKID by hashing public key */
+ if (kid_type == SKID_TYPE) {
+ ret = CalcHashId(buf, bufferSz, cert->skid);
+ cert->skidSz = KEYID_SIZE;
+ }
+ else if (kid_type == AKID_TYPE) {
+ ret = CalcHashId(buf, bufferSz, cert->akid);
+ cert->akidSz = KEYID_SIZE;
+ }
+ else
+ ret = BAD_FUNC_ARG;
+
+ XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
+ ed448Key, SKID_TYPE);
+}
+
+/* Set SKID from RSA or ECC public key */
+int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
+{
+ return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, NULL,
+ SKID_TYPE);
+}
+
+#ifdef HAVE_NTRU
+/* Set SKID from NTRU public key */
+int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert,
+ byte *ntruKey, word16 ntruKeySz)
+{
+ return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, NULL,
+ SKID_TYPE);
+}
+#endif
+
+int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key)
+{
+ RsaKey* rsaKey = NULL;
+ ecc_key* eccKey = NULL;
+ ed25519_key* ed25519Key = NULL;
+ ed448_key* ed448Key = NULL;
+
+ if (keyType == RSA_TYPE)
+ rsaKey = (RsaKey*)key;
+ else if (keyType == ECC_TYPE)
+ eccKey = (ecc_key*)key;
+ else if (keyType == ED25519_TYPE)
+ ed25519Key = (ed25519_key*)key;
+ else if (keyType == ED448_TYPE)
+ ed448Key = (ed448_key*)key;
+
+ return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key,
+ ed448Key, AKID_TYPE);
+}
+
+/* Set SKID from RSA or ECC public key */
+int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey)
+{
+ return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, NULL,
+ AKID_TYPE);
+}
+
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_ASN_CRYPT)
+
+/* Set SKID from public key file in PEM */
+int wc_SetSubjectKeyId(Cert *cert, const char* file)
+{
+ int ret, derSz;
+ byte* der;
+ word32 idx;
+ RsaKey *rsakey = NULL;
+ ecc_key *eckey = NULL;
+
+ if (cert == NULL || file == NULL)
+ return BAD_FUNC_ARG;
+
+ der = (byte*)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, DYNAMIC_TYPE_CERT);
+ if (der == NULL) {
+ WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem");
+ return MEMORY_E;
+ }
+ derSz = MAX_PUBLIC_KEY_SZ;
+
+ XMEMSET(der, 0, derSz);
+ derSz = wc_PemPubKeyToDer(file, der, derSz);
+ if (derSz <= 0) {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return derSz;
+ }
-#ifdef WOLFSSL_SMALL_STACK
- decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (decoded == NULL)
+ /* Load PubKey in internal structure */
+#ifndef NO_RSA
+ rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), cert->heap, DYNAMIC_TYPE_RSA);
+ if (rsakey == NULL) {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return MEMORY_E;
+ }
+
+ if (wc_InitRsaKey(rsakey, cert->heap) != 0) {
+ WOLFSSL_MSG("wc_InitRsaKey failure");
+ XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return MEMORY_E;
+ }
+
+ idx = 0;
+ ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz);
+ if (ret != 0)
#endif
-
- InitDecodedCert(decoded, (byte*)der, derSz, 0);
- ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
+ {
+#ifndef NO_RSA
+ WOLFSSL_MSG("wc_RsaPublicKeyDecode failed");
+ wc_FreeRsaKey(rsakey);
+ XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+ rsakey = NULL;
+#endif
+#ifdef HAVE_ECC
+ /* Check to load ecc public key */
+ eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), cert->heap,
+ DYNAMIC_TYPE_ECC);
+ if (eckey == NULL) {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return MEMORY_E;
+ }
- if (ret < 0) {
- WOLFSSL_MSG("ParseCertRelative error");
+ if (wc_ecc_init(eckey) != 0) {
+ WOLFSSL_MSG("wc_ecc_init failure");
+ wc_ecc_free(eckey);
+ XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return MEMORY_E;
+ }
+
+ idx = 0;
+ ret = wc_EccPublicKeyDecode(der, &idx, eckey, derSz);
+ if (ret != 0) {
+ WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ wc_ecc_free(eckey);
+ XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+ return PUBLIC_KEY_E;
+ }
+#else
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return PUBLIC_KEY_E;
+#endif /* HAVE_ECC */
+ }
+
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+ ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey);
+
+#ifndef NO_RSA
+ wc_FreeRsaKey(rsakey);
+ XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA);
+#endif
+#ifdef HAVE_ECC
+ wc_ecc_free(eckey);
+ XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC);
+#endif
+ return ret;
+}
+
+#endif /* !NO_FILESYSTEM && !NO_ASN_CRYPT */
+
+static int SetAuthKeyIdFromDcert(Cert* cert, DecodedCert* decoded)
+{
+ int ret = 0;
+
+ /* Subject Key Id not found !! */
+ if (decoded->extSubjKeyIdSet == 0) {
+ ret = ASN_NO_SKID;
+ }
+
+ /* SKID invalid size */
+ else if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) {
+ ret = MEMORY_E;
+ }
+
+ else {
+ /* Put the SKID of CA to AKID of certificate */
+ XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE);
+ cert->akidSz = KEYID_SIZE;
+ }
+
+ return ret;
+}
+
+/* Set AKID from certificate contains in buffer (DER encoded) */
+int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz)
+{
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ ret = SetAuthKeyIdFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
+}
+
+
+#ifndef NO_FILESYSTEM
+
+/* Set AKID from certificate file in PEM */
+int wc_SetAuthKeyId(Cert *cert, const char* file)
+{
+ int ret;
+ int derSz;
+ byte* der;
+
+ if (cert == NULL || file == NULL)
+ return BAD_FUNC_ARG;
+
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
+ if (der == NULL) {
+ WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem");
+ return MEMORY_E;
+ }
+
+ derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
+ if (derSz <= 0)
+ {
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+ return derSz;
}
- else if (decoded->extensions) {
- byte b;
+
+ ret = wc_SetAuthKeyIdFromCert(cert, der, derSz);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
+
+ return ret;
+}
+
+#endif /* !NO_FILESYSTEM */
+
+/* Set KeyUsage from human readable string */
+int wc_SetKeyUsage(Cert *cert, const char *value)
+{
+ int ret = 0;
+ char *token, *str, *ptr;
+ word32 len;
+
+ if (cert == NULL || value == NULL)
+ return BAD_FUNC_ARG;
+
+ cert->keyUsage = 0;
+
+ /* duplicate string (including terminator) */
+ len = (word32)XSTRLEN(value);
+ str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL)
+ return MEMORY_E;
+ XMEMCPY(str, value, len+1);
+
+ /* parse value, and set corresponding Key Usage value */
+ if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return KEYUSAGE_E;
+ }
+ while (token != NULL)
+ {
+ len = (word32)XSTRLEN(token);
+
+ if (!XSTRNCASECMP(token, "digitalSignature", len))
+ cert->keyUsage |= KEYUSE_DIGITAL_SIG;
+ else if (!XSTRNCASECMP(token, "nonRepudiation", len) ||
+ !XSTRNCASECMP(token, "contentCommitment", len))
+ cert->keyUsage |= KEYUSE_CONTENT_COMMIT;
+ else if (!XSTRNCASECMP(token, "keyEncipherment", len))
+ cert->keyUsage |= KEYUSE_KEY_ENCIPHER;
+ else if (!XSTRNCASECMP(token, "dataEncipherment", len))
+ cert->keyUsage |= KEYUSE_DATA_ENCIPHER;
+ else if (!XSTRNCASECMP(token, "keyAgreement", len))
+ cert->keyUsage |= KEYUSE_KEY_AGREE;
+ else if (!XSTRNCASECMP(token, "keyCertSign", len))
+ cert->keyUsage |= KEYUSE_KEY_CERT_SIGN;
+ else if (!XSTRNCASECMP(token, "cRLSign", len))
+ cert->keyUsage |= KEYUSE_CRL_SIGN;
+ else if (!XSTRNCASECMP(token, "encipherOnly", len))
+ cert->keyUsage |= KEYUSE_ENCIPHER_ONLY;
+ else if (!XSTRNCASECMP(token, "decipherOnly", len))
+ cert->keyUsage |= KEYUSE_DECIPHER_ONLY;
+ else {
+ ret = KEYUSAGE_E;
+ break;
+ }
+
+ token = XSTRTOK(NULL, ",", &ptr);
+ }
+
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+/* Set ExtendedKeyUsage from human readable string */
+int wc_SetExtKeyUsage(Cert *cert, const char *value)
+{
+ int ret = 0;
+ char *token, *str, *ptr;
+ word32 len;
+
+ if (cert == NULL || value == NULL)
+ return BAD_FUNC_ARG;
+
+ cert->extKeyUsage = 0;
+
+ /* duplicate string (including terminator) */
+ len = (word32)XSTRLEN(value);
+ str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL)
+ return MEMORY_E;
+ XMEMCPY(str, value, len+1);
+
+ /* parse value, and set corresponding Key Usage value */
+ if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return EXTKEYUSAGE_E;
+ }
+
+ while (token != NULL)
+ {
+ len = (word32)XSTRLEN(token);
+
+ if (!XSTRNCASECMP(token, "any", len))
+ cert->extKeyUsage |= EXTKEYUSE_ANY;
+ else if (!XSTRNCASECMP(token, "serverAuth", len))
+ cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH;
+ else if (!XSTRNCASECMP(token, "clientAuth", len))
+ cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
+ else if (!XSTRNCASECMP(token, "codeSigning", len))
+ cert->extKeyUsage |= EXTKEYUSE_CODESIGN;
+ else if (!XSTRNCASECMP(token, "emailProtection", len))
+ cert->extKeyUsage |= EXTKEYUSE_EMAILPROT;
+ else if (!XSTRNCASECMP(token, "timeStamping", len))
+ cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP;
+ else if (!XSTRNCASECMP(token, "OCSPSigning", len))
+ cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN;
+ else {
+ ret = EXTKEYUSAGE_E;
+ break;
+ }
+
+ token = XSTRTOK(NULL, ",", &ptr);
+ }
+
+ XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+}
+
+#ifdef WOLFSSL_EKU_OID
+/*
+ * cert structure to set EKU oid in
+ * oid the oid in byte representation
+ * sz size of oid buffer
+ * idx index of array to place oid
+ *
+ * returns 0 on success
+ */
+int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx,
+ void* heap)
+{
+ byte oid[MAX_OID_SZ];
+ word32 oidSz = MAX_OID_SZ;
+
+ if (idx >= CTC_MAX_EKU_NB || sz >= CTC_MAX_EKU_OID_SZ) {
+ WOLFSSL_MSG("Either idx or sz was too large");
+ return BAD_FUNC_ARG;
+ }
+
+ if (EncodePolicyOID(oid, &oidSz, in, heap) != 0) {
+ return BUFFER_E;
+ }
+
+ XMEMCPY(cert->extKeyUsageOID[idx], oid, oidSz);
+ cert->extKeyUsageOIDSz[idx] = oidSz;
+ cert->extKeyUsage |= EXTKEYUSE_USER;
+
+ return 0;
+}
+#endif /* WOLFSSL_EKU_OID */
+#endif /* WOLFSSL_CERT_EXT */
+
+
+#ifdef WOLFSSL_ALT_NAMES
+
+static int SetAltNamesFromDcert(Cert* cert, DecodedCert* decoded)
+{
+ int ret = 0;
+ byte tag;
+
+ if (decoded->extensions) {
int length;
word32 maxExtensionsIdx;
decoded->srcIdx = decoded->extensionsIdx;
- b = decoded->source[decoded->srcIdx++];
-
- if (b != ASN_EXTENSIONS) {
+ if (GetASNTag(decoded->source, &decoded->srcIdx, &tag, decoded->maxIdx)
+ != 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != ASN_EXTENSIONS) {
ret = ASN_PARSE_E;
}
else if (GetLength(decoded->source, &decoded->srcIdx, &length,
@@ -6244,7 +14471,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
decoded->srcIdx = startIdx;
if (GetAlgoId(decoded->source, &decoded->srcIdx, &oid,
- decoded->maxIdx) < 0) {
+ oidCertExtType, decoded->maxIdx) < 0) {
ret = ASN_PARSE_E;
break;
}
@@ -6267,17 +14494,13 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
}
}
- FreeDecodedCert(decoded);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
- return ret < 0 ? ret : 0;
+ return ret;
}
+#ifndef NO_FILESYSTEM
-/* Set Dates from der cert, return 0 on success */
-static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
+/* Set Alt Names from der cert, return 0 on success */
+static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz)
{
int ret;
#ifdef WOLFSSL_SMALL_STACK
@@ -6286,28 +14509,45 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
DecodedCert decoded[1];
#endif
- WOLFSSL_ENTER("SetDatesFromCert");
if (derSz < 0)
return derSz;
-
+
#ifdef WOLFSSL_SMALL_STACK
- decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
+ decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (decoded == NULL)
return MEMORY_E;
#endif
- InitDecodedCert(decoded, (byte*)der, derSz, 0);
+ InitDecodedCert(decoded, der, derSz, NULL);
ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
if (ret < 0) {
WOLFSSL_MSG("ParseCertRelative error");
}
- else if (decoded->beforeDate == NULL || decoded->afterDate == NULL) {
+ else {
+ ret = SetAltNamesFromDcert(cert, decoded);
+ }
+
+ FreeDecodedCert(decoded);
+#ifdef WOLFSSL_SMALL_STACK
+ XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+ return ret < 0 ? ret : 0;
+}
+
+#endif
+
+static int SetDatesFromDcert(Cert* cert, DecodedCert* decoded)
+{
+ int ret = 0;
+
+ if (decoded->beforeDate == NULL || decoded->afterDate == NULL) {
WOLFSSL_MSG("Couldn't extract dates");
ret = -1;
}
- else if (decoded->beforeDateLen > MAX_DATE_SIZE ||
+ else if (decoded->beforeDateLen > MAX_DATE_SIZE ||
decoded->afterDateLen > MAX_DATE_SIZE) {
WOLFSSL_MSG("Bad date size");
ret = -1;
@@ -6320,23 +14560,108 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz)
cert->afterDateSz = decoded->afterDateLen;
}
- FreeDecodedCert(decoded);
-
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-#endif
-
- return ret < 0 ? ret : 0;
+ return ret;
}
+#endif /* WOLFSSL_ALT_NAMES */
-#endif /* WOLFSSL_ALT_NAMES && !NO_RSA */
+static void SetNameFromDcert(CertName* cn, DecodedCert* decoded)
+{
+ int sz;
+
+ if (decoded->subjectCN) {
+ sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->commonName, decoded->subjectCN, sz);
+ cn->commonName[sz] = '\0';
+ cn->commonNameEnc = decoded->subjectCNEnc;
+ }
+ if (decoded->subjectC) {
+ sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->country, decoded->subjectC, sz);
+ cn->country[sz] = '\0';
+ cn->countryEnc = decoded->subjectCEnc;
+ }
+ if (decoded->subjectST) {
+ sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->state, decoded->subjectST, sz);
+ cn->state[sz] = '\0';
+ cn->stateEnc = decoded->subjectSTEnc;
+ }
+ if (decoded->subjectL) {
+ sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->locality, decoded->subjectL, sz);
+ cn->locality[sz] = '\0';
+ cn->localityEnc = decoded->subjectLEnc;
+ }
+ if (decoded->subjectO) {
+ sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->org, decoded->subjectO, sz);
+ cn->org[sz] = '\0';
+ cn->orgEnc = decoded->subjectOEnc;
+ }
+ if (decoded->subjectOU) {
+ sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->unit, decoded->subjectOU, sz);
+ cn->unit[sz] = '\0';
+ cn->unitEnc = decoded->subjectOUEnc;
+ }
+ if (decoded->subjectSN) {
+ sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->sur, decoded->subjectSN, sz);
+ cn->sur[sz] = '\0';
+ cn->surEnc = decoded->subjectSNEnc;
+ }
+ if (decoded->subjectSND) {
+ sz = (decoded->subjectSNDLen < CTC_NAME_SIZE) ? decoded->subjectSNDLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->serialDev, decoded->subjectSND, sz);
+ cn->serialDev[sz] = '\0';
+ cn->serialDevEnc = decoded->subjectSNDEnc;
+ }
+#ifdef WOLFSSL_CERT_EXT
+ if (decoded->subjectBC) {
+ sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->busCat, decoded->subjectBC, sz);
+ cn->busCat[sz] = '\0';
+ cn->busCatEnc = decoded->subjectBCEnc;
+ }
+ if (decoded->subjectJC) {
+ sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->joiC, decoded->subjectJC, sz);
+ cn->joiC[sz] = '\0';
+ cn->joiCEnc = decoded->subjectJCEnc;
+ }
+ if (decoded->subjectJS) {
+ sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen
+ : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->joiSt, decoded->subjectJS, sz);
+ cn->joiSt[sz] = '\0';
+ cn->joiStEnc = decoded->subjectJSEnc;
+ }
+#endif
+ if (decoded->subjectEmail) {
+ sz = (decoded->subjectEmailLen < CTC_NAME_SIZE)
+ ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1;
+ XSTRNCPY(cn->email, decoded->subjectEmail, sz);
+ cn->email[sz] = '\0';
+ }
+}
+#ifndef NO_FILESYSTEM
/* Set cn name from der buffer, return 0 on success */
static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
{
- int ret, sz;
+ int ret;
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* decoded;
#else
@@ -6353,68 +14678,14 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
return MEMORY_E;
#endif
- InitDecodedCert(decoded, (byte*)der, derSz, 0);
+ InitDecodedCert(decoded, der, derSz, NULL);
ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0);
if (ret < 0) {
WOLFSSL_MSG("ParseCertRelative error");
}
else {
- if (decoded->subjectCN) {
- sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE);
- cn->commonName[sz] = 0;
- cn->commonNameEnc = decoded->subjectCNEnc;
- }
- if (decoded->subjectC) {
- sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->country, decoded->subjectC, CTC_NAME_SIZE);
- cn->country[sz] = 0;
- cn->countryEnc = decoded->subjectCEnc;
- }
- if (decoded->subjectST) {
- sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->state, decoded->subjectST, CTC_NAME_SIZE);
- cn->state[sz] = 0;
- cn->stateEnc = decoded->subjectSTEnc;
- }
- if (decoded->subjectL) {
- sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->locality, decoded->subjectL, CTC_NAME_SIZE);
- cn->locality[sz] = 0;
- cn->localityEnc = decoded->subjectLEnc;
- }
- if (decoded->subjectO) {
- sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->org, decoded->subjectO, CTC_NAME_SIZE);
- cn->org[sz] = 0;
- cn->orgEnc = decoded->subjectOEnc;
- }
- if (decoded->subjectOU) {
- sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->unit, decoded->subjectOU, CTC_NAME_SIZE);
- cn->unit[sz] = 0;
- cn->unitEnc = decoded->subjectOUEnc;
- }
- if (decoded->subjectSN) {
- sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen
- : CTC_NAME_SIZE - 1;
- strncpy(cn->sur, decoded->subjectSN, CTC_NAME_SIZE);
- cn->sur[sz] = 0;
- cn->surEnc = decoded->subjectSNEnc;
- }
- if (decoded->subjectEmail) {
- sz = (decoded->subjectEmailLen < CTC_NAME_SIZE)
- ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1;
- strncpy(cn->email, decoded->subjectEmail, CTC_NAME_SIZE);
- cn->email[sz] = 0;
- }
+ SetNameFromDcert(cn, decoded);
}
FreeDecodedCert(decoded);
@@ -6426,24 +14697,26 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz)
return ret < 0 ? ret : 0;
}
-
-#ifndef NO_FILESYSTEM
-
/* Set cert issuer from issuerFile in PEM */
int wc_SetIssuer(Cert* cert, const char* issuerFile)
{
int ret;
int derSz;
- byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
+ byte* der;
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
if (der == NULL) {
WOLFSSL_MSG("wc_SetIssuer OOF Problem");
return MEMORY_E;
}
- derSz = wolfSSL_PemCertToDer(issuerFile, der, EIGHTK_BUF);
+ derSz = wc_PemCertToDer(issuerFile, der, EIGHTK_BUF);
cert->selfSigned = 0;
ret = SetNameFromCert(&cert->issuer, der, derSz);
- XFREE(der, NULL, DYNAMIC_TYPE_CERT);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return ret;
}
@@ -6454,77 +14727,367 @@ int wc_SetSubject(Cert* cert, const char* subjectFile)
{
int ret;
int derSz;
- byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
+ byte* der;
+
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
if (der == NULL) {
WOLFSSL_MSG("wc_SetSubject OOF Problem");
return MEMORY_E;
}
- derSz = wolfSSL_PemCertToDer(subjectFile, der, EIGHTK_BUF);
+
+ derSz = wc_PemCertToDer(subjectFile, der, EIGHTK_BUF);
ret = SetNameFromCert(&cert->subject, der, derSz);
- XFREE(der, NULL, DYNAMIC_TYPE_CERT);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return ret;
}
-
#ifdef WOLFSSL_ALT_NAMES
-/* Set atl names from file in PEM */
+/* Set alt names from file in PEM */
int wc_SetAltNames(Cert* cert, const char* file)
{
int ret;
int derSz;
- byte* der = (byte*)XMALLOC(EIGHTK_BUF, NULL, DYNAMIC_TYPE_CERT);
+ byte* der;
+
+ if (cert == NULL) {
+ return BAD_FUNC_ARG;
+ }
+ der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT);
if (der == NULL) {
WOLFSSL_MSG("wc_SetAltNames OOF Problem");
return MEMORY_E;
}
- derSz = wolfSSL_PemCertToDer(file, der, EIGHTK_BUF);
+ derSz = wc_PemCertToDer(file, der, EIGHTK_BUF);
ret = SetAltNamesFromCert(cert, der, derSz);
- XFREE(der, NULL, DYNAMIC_TYPE_CERT);
+ XFREE(der, cert->heap, DYNAMIC_TYPE_CERT);
return ret;
}
#endif /* WOLFSSL_ALT_NAMES */
-#endif /* NO_FILESYSTEM */
+#endif /* !NO_FILESYSTEM */
/* Set cert issuer from DER buffer */
int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz)
{
- cert->selfSigned = 0;
- return SetNameFromCert(&cert->issuer, der, derSz);
-}
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ cert->selfSigned = 0;
+
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+ if (ret >= 0) {
+ SetNameFromDcert(&cert->issuer, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
+}
/* Set cert subject from DER buffer */
int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz)
{
- return SetNameFromCert(&cert->subject, der, derSz);
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ SetNameFromDcert(&cert->subject, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
+}
+#ifdef WOLFSSL_CERT_EXT
+/* Set cert raw subject from DER buffer */
+int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz)
+{
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ if ((((DecodedCert*)cert->decodedCert)->subjectRaw) &&
+ (((DecodedCert*)cert->decodedCert)->subjectRawLen <=
+ (int)sizeof(CertName))) {
+ XMEMCPY(cert->sbjRaw,
+ ((DecodedCert*)cert->decodedCert)->subjectRaw,
+ ((DecodedCert*)cert->decodedCert)->subjectRawLen);
+ }
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return ret;
}
+/* Set cert raw issuer from DER buffer */
+int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz)
+{
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ if ((((DecodedCert*)cert->decodedCert)->issuerRaw) &&
+ (((DecodedCert*)cert->decodedCert)->issuerRawLen <=
+ (int)sizeof(CertName))) {
+ XMEMCPY(cert->issRaw,
+ ((DecodedCert*)cert->decodedCert)->issuerRaw,
+ ((DecodedCert*)cert->decodedCert)->issuerRawLen);
+ }
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+ return ret;
+}
+#endif
#ifdef WOLFSSL_ALT_NAMES
/* Set cert alt names from DER buffer */
int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz)
{
- return SetAltNamesFromCert(cert, der, derSz);
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ ret = SetAltNamesFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return(ret);
}
/* Set cert dates from DER buffer */
int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz)
{
- return SetDatesFromCert(cert, der, derSz);
+ int ret = 0;
+
+ if (cert == NULL) {
+ ret = BAD_FUNC_ARG;
+ }
+ else {
+ /* Check if decodedCert is cached */
+ if (cert->der != der) {
+ /* Allocate cache for the decoded cert */
+ ret = wc_SetCert_LoadDer(cert, der, derSz);
+ }
+
+ if (ret >= 0) {
+ ret = SetDatesFromDcert(cert, (DecodedCert*)cert->decodedCert);
+#ifndef WOLFSSL_CERT_GEN_CACHE
+ wc_SetCert_Free(cert);
+#endif
+ }
+ }
+
+ return(ret);
}
#endif /* WOLFSSL_ALT_NAMES */
#endif /* WOLFSSL_CERT_GEN */
+#if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) \
+ || defined(OPENSSL_EXTRA)
+/* Encode OID string representation to ITU-T X.690 format */
+int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap)
+{
+ word32 val, idx = 0, nb_val;
+ char *token, *str, *ptr;
+ word32 len;
+
+ (void)heap;
+
+ if (out == NULL || outSz == NULL || *outSz < 2 || in == NULL)
+ return BAD_FUNC_ARG;
+
+ /* duplicate string (including terminator) */
+ len = (word32)XSTRLEN(in);
+ str = (char *)XMALLOC(len+1, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (str == NULL)
+ return MEMORY_E;
+ XMEMCPY(str, in, len+1);
+
+ nb_val = 0;
+
+ /* parse value, and set corresponding Policy OID value */
+ token = XSTRTOK(str, ".", &ptr);
+ while (token != NULL)
+ {
+ val = (word32)XATOI(token);
+
+ if (nb_val == 0) {
+ if (val > 2) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ASN_OBJECT_ID_E;
+ }
+
+ out[idx] = (byte)(40 * val);
+ }
+ else if (nb_val == 1) {
+ if (val > 127) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ASN_OBJECT_ID_E;
+ }
+
+ if (idx > *outSz) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return BUFFER_E;
+ }
+
+ out[idx++] += (byte)val;
+ }
+ else {
+ word32 tb = 0, x;
+ int i = 0;
+ byte oid[MAX_OID_SZ];
+
+ while (val >= 128) {
+ x = val % 128;
+ val /= 128;
+ oid[i++] = (byte) (((tb++) ? 0x80 : 0) | x);
+ }
+
+ if ((idx+(word32)i) > *outSz) {
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return BUFFER_E;
+ }
+
+ oid[i] = (byte) (((tb++) ? 0x80 : 0) | val);
+
+ /* push value in the right order */
+ while (i >= 0)
+ out[idx++] = oid[i--];
+ }
+
+ token = XSTRTOK(NULL, ".", &ptr);
+ nb_val++;
+ }
+
+ *outSz = idx;
+
+ XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return 0;
+}
+#endif /* WOLFSSL_CERT_EXT || OPENSSL_EXTRA */
+
+#endif /* !NO_CERTS */
+
+#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+/* Helper function for wolfSSL_i2d_DHparams */
+int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g)
+{
+ word32 idx = 0;
+ int pSz;
+ int gSz;
+ unsigned int tmp;
+ word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
+
+ /* If the leading bit on the INTEGER is a 1, add a leading zero */
+ int pLeadingZero = mp_leading_bit(p);
+ int gLeadingZero = mp_leading_bit(g);
+ int pLen = mp_unsigned_bin_size(p);
+ int gLen = mp_unsigned_bin_size(g);
+
+ WOLFSSL_ENTER("StoreDHparams");
+ if (out == NULL) {
+ WOLFSSL_MSG("Null buffer error");
+ return BUFFER_E;
+ }
+
+ tmp = pLeadingZero + gLeadingZero + pLen + gLen;
+ if (*outLen < (tmp + headerSz)) {
+ return BUFFER_E;
+ }
+
+ /* Set sequence */
+ idx = SetSequence(tmp + headerSz + 2, out);
+
+ /* Encode p */
+ pSz = SetASNIntMP(p, -1, &out[idx]);
+ if (pSz < 0) {
+ WOLFSSL_MSG("SetASNIntMP failed");
+ return pSz;
+ }
+ idx += pSz;
+
+ /* Encode g */
+ gSz = SetASNIntMP(g, -1, &out[idx]);
+ if (gSz < 0) {
+ WOLFSSL_MSG("SetASNIntMP failed");
+ return gSz;
+ }
+ idx += gSz;
+
+ *outLen = idx;
+
+ return 0;
+}
+#endif /* !NO_DH && WOLFSSL_QT || OPENSSL_ALL */
#ifdef HAVE_ECC
@@ -6532,8 +15095,8 @@ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz)
int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
{
word32 idx = 0;
- word32 rSz; /* encoding size */
- word32 sSz;
+ int rSz; /* encoding size */
+ int sSz;
word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
/* If the leading bit on the INTEGER is a 1, add a leading zero */
@@ -6541,33 +15104,24 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
int sLeadingZero = mp_leading_bit(s);
int rLen = mp_unsigned_bin_size(r); /* big int size */
int sLen = mp_unsigned_bin_size(s);
- int err;
if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero +
headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */
- return BAD_FUNC_ARG;
+ return BUFFER_E;
- idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out);
+ idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out);
/* store r */
- out[idx++] = ASN_INTEGER;
- rSz = SetLength(rLen + rLeadingZero, &out[idx]);
+ rSz = SetASNIntMP(r, -1, &out[idx]);
+ if (rSz < 0)
+ return rSz;
idx += rSz;
- if (rLeadingZero)
- out[idx++] = 0;
- err = mp_to_unsigned_bin(r, &out[idx]);
- if (err != MP_OKAY) return err;
- idx += rLen;
/* store s */
- out[idx++] = ASN_INTEGER;
- sSz = SetLength(sLen + sLeadingZero, &out[idx]);
+ sSz = SetASNIntMP(s, -1, &out[idx]);
+ if (sSz < 0)
+ return sSz;
idx += sSz;
- if (sLeadingZero)
- out[idx++] = 0;
- err = mp_to_unsigned_bin(s, &out[idx]);
- if (err != MP_OKAY) return err;
- idx += sLen;
*outLen = idx;
@@ -6575,23 +15129,35 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
}
-/* Der Decode ECC-DSA Signautre, r & s stored as big ints */
+/* Der Decode ECC-DSA Signature, r & s stored as big ints */
int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
{
word32 idx = 0;
int len = 0;
- if (GetSequence(sig, &idx, &len, sigLen) < 0)
+ if (GetSequence(sig, &idx, &len, sigLen) < 0) {
return ASN_ECC_KEY_E;
+ }
- if ((word32)len > (sigLen - idx))
+#ifndef NO_STRICT_ECDSA_LEN
+ /* enable strict length checking for signature */
+ if (sigLen != idx + (word32)len) {
+ return ASN_ECC_KEY_E;
+ }
+#else
+ /* allow extra signature bytes at end */
+ if ((word32)len > (sigLen - idx)) {
return ASN_ECC_KEY_E;
+ }
+#endif
- if (GetInt(r, sig, &idx, sigLen) < 0)
+ if (GetInt(r, sig, &idx, sigLen) < 0) {
return ASN_ECC_KEY_E;
+ }
- if (GetInt(s, sig, &idx, sigLen) < 0)
+ if (GetInt(s, sig, &idx, sigLen) < 0) {
return ASN_ECC_KEY_E;
+ }
return 0;
}
@@ -6600,18 +15166,20 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
word32 inSz)
{
- word32 oid = 0;
+ word32 oidSum;
int version, length;
- int privSz, pubSz;
+ int privSz, pubSz = 0;
byte b;
int ret = 0;
+ int curve_id = ECC_CURVE_DEF;
#ifdef WOLFSSL_SMALL_STACK
byte* priv;
byte* pub;
#else
- byte priv[ECC_MAXSIZE];
- byte pub[ECC_MAXSIZE * 2 + 1]; /* public key has two parts plus header */
+ byte priv[ECC_MAXSIZE+1];
+ byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */
#endif
+ byte* pubData = NULL;
if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
return BAD_FUNC_ARG;
@@ -6619,14 +15187,17 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
- if (GetMyVersion(input, inOutIdx, &version) < 0)
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (*inOutIdx >= inSz)
return ASN_PARSE_E;
b = input[*inOutIdx];
*inOutIdx += 1;
/* priv type */
- if (b != 4 && b != 6 && b != 7)
+ if (b != 4 && b != 6 && b != 7)
return ASN_PARSE_E;
if (GetLength(input, inOutIdx, &length, inSz) < 0)
@@ -6636,13 +15207,13 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
return BUFFER_E;
#ifdef WOLFSSL_SMALL_STACK
- priv = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ priv = (byte*)XMALLOC(ECC_MAXSIZE+1, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (priv == NULL)
return MEMORY_E;
-
- pub = (byte*)XMALLOC(ECC_MAXSIZE * 2 + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+ pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), key->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (pub == NULL) {
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
@@ -6652,36 +15223,30 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
XMEMCPY(priv, &input[*inOutIdx], privSz);
*inOutIdx += length;
- /* prefix 0, may have */
- b = input[*inOutIdx];
- if (b == ECC_PREFIX_0) {
- *inOutIdx += 1;
-
- if (GetLength(input, inOutIdx, &length, inSz) < 0)
- ret = ASN_PARSE_E;
- else {
- /* object id */
- b = input[*inOutIdx];
+ if ((*inOutIdx + 1) < inSz) {
+ /* prefix 0, may have */
+ b = input[*inOutIdx];
+ if (b == ECC_PREFIX_0) {
*inOutIdx += 1;
- if (b != ASN_OBJECT_ID) {
- ret = ASN_OBJECT_ID_E;
- }
- else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
+ if (GetLength(input, inOutIdx, &length, inSz) <= 0)
ret = ASN_PARSE_E;
- }
else {
- while(length--) {
- oid += input[*inOutIdx];
- *inOutIdx += 1;
+ ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType,
+ inSz);
+ if (ret == 0) {
+ if ((ret = CheckCurve(oidSum)) < 0)
+ ret = ECC_CURVE_OID_E;
+ else {
+ curve_id = ret;
+ ret = 0;
+ }
}
- if (CheckCurve(oid) < 0)
- ret = ECC_CURVE_OID_E;
}
}
}
- if (ret == 0) {
+ if (ret == 0 && (*inOutIdx + 1) < inSz) {
/* prefix 1 */
b = input[*inOutIdx];
*inOutIdx += 1;
@@ -6689,142 +15254,879 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
if (b != ECC_PREFIX_1) {
ret = ASN_ECC_KEY_E;
}
- else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
+ else if (GetLength(input, inOutIdx, &length, inSz) <= 0) {
ret = ASN_PARSE_E;
}
else {
/* key header */
- b = input[*inOutIdx];
- *inOutIdx += 1;
-
- if (b != ASN_BIT_STRING) {
- ret = ASN_BITSTR_E;
- }
- else if (GetLength(input, inOutIdx, &length, inSz) < 0) {
- ret = ASN_PARSE_E;
- }
- else {
- b = input[*inOutIdx];
- *inOutIdx += 1;
-
- if (b != 0x00) {
- ret = ASN_EXPECT_0_E;
- }
- else {
- /* pub key */
- pubSz = length - 1; /* null prefix */
- if (pubSz < (ECC_MAXSIZE*2 + 1)) {
- XMEMCPY(pub, &input[*inOutIdx], pubSz);
- *inOutIdx += length;
- ret = wc_ecc_import_private_key(priv, privSz, pub, pubSz,
- key);
- } else
- ret = BUFFER_E;
+ ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL);
+ if (ret == 0) {
+ /* pub key */
+ pubSz = length;
+ if (pubSz < 2*(ECC_MAXSIZE+1)) {
+ XMEMCPY(pub, &input[*inOutIdx], pubSz);
+ *inOutIdx += length;
+ pubData = pub;
}
+ else
+ ret = BUFFER_E;
}
}
}
+ if (ret == 0) {
+ ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key,
+ curve_id);
+ }
+
#ifdef WOLFSSL_SMALL_STACK
- XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
-#ifdef WOLFSSL_KEY_GEN
+#ifdef WOLFSSL_CUSTOM_CURVES
+static void ByteToHex(byte n, char* str)
+{
+ const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-/* Write a Private ecc key to DER format, length on success else < 0 */
-int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
+ str[0] = hexChar[n >> 4];
+ str[1] = hexChar[n & 0xf];
+}
+
+/* returns 0 on success */
+static int ASNToHexString(const byte* input, word32* inOutIdx, char** out,
+ word32 inSz, void* heap, int heapType)
+{
+ int len;
+ int i;
+ char* str;
+ word32 localIdx;
+ byte tag;
+
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
+ }
+
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) == 0 && tag == ASN_INTEGER) {
+ if (GetASNInt(input, inOutIdx, &len, inSz) < 0)
+ return ASN_PARSE_E;
+ }
+ else {
+ if (GetOctetString(input, inOutIdx, &len, inSz) < 0)
+ return ASN_PARSE_E;
+ }
+
+ str = (char*)XMALLOC(len * 2 + 1, heap, heapType);
+ for (i=0; i<len; i++)
+ ByteToHex(input[*inOutIdx + i], str + i*2);
+ str[len*2] = '\0';
+
+ *inOutIdx += len;
+ *out = str;
+
+ (void)heap;
+ (void)heapType;
+
+ return 0;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+#ifdef WOLFSSL_CUSTOM_CURVES
+static int EccKeyParamCopy(char** dst, char* src)
+{
+ int ret = 0;
+#ifdef WOLFSSL_ECC_CURVE_STATIC
+ word32 length;
+#endif
+
+ if (dst == NULL || src == NULL)
+ return BAD_FUNC_ARG;
+
+#ifndef WOLFSSL_ECC_CURVE_STATIC
+ *dst = src;
+#else
+ length = (int)XSTRLEN(src) + 1;
+ if (length > MAX_ECC_STRING) {
+ WOLFSSL_MSG("ECC Param too large for buffer");
+ ret = BUFFER_E;
+ }
+ else {
+ XSTRNCPY(*dst, src, length);
+ }
+ XFREE(src, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+#endif
+
+ return ret;
+}
+#endif /* WOLFSSL_CUSTOM_CURVES */
+
+int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
+ ecc_key* key, word32 inSz)
+{
+ int length;
+ int ret;
+ int curve_id = ECC_CURVE_DEF;
+ word32 oidSum, localIdx;
+ byte tag;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = SkipObjectId(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+
+ if (*inOutIdx >= inSz) {
+ return BUFFER_E;
+ }
+
+ localIdx = *inOutIdx;
+ if (GetASNTag(input, &localIdx, &tag, inSz) == 0 &&
+ tag == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
+#ifdef WOLFSSL_CUSTOM_CURVES
+ ecc_set_type* curve;
+ int len;
+ char* point = NULL;
+
+ ret = 0;
+
+ curve = (ecc_set_type*)XMALLOC(sizeof(*curve), key->heap,
+ DYNAMIC_TYPE_ECC_BUFFER);
+ if (curve == NULL)
+ ret = MEMORY_E;
+
+ if (ret == 0) {
+ static const char customName[] = "Custom";
+ XMEMSET(curve, 0, sizeof(*curve));
+ #ifndef WOLFSSL_ECC_CURVE_STATIC
+ curve->name = customName;
+ #else
+ XMEMCPY((void*)curve->name, customName, sizeof(customName));
+ #endif
+ curve->id = ECC_CURVE_CUSTOM;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+
+ if (ret == 0) {
+ GetInteger7Bit(input, inOutIdx, inSz);
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ char* p = NULL;
+ SkipObjectId(input, inOutIdx, inSz);
+ ret = ASNToHexString(input, inOutIdx, &p, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->prime, p);
+ }
+ if (ret == 0) {
+ curve->size = (int)XSTRLEN(curve->prime) / 2;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ ret = ASN_PARSE_E;
+ }
+ if (ret == 0) {
+ char* af = NULL;
+ ret = ASNToHexString(input, inOutIdx, &af, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->Af, af);
+ }
+ if (ret == 0) {
+ char* bf = NULL;
+ ret = ASNToHexString(input, inOutIdx, &bf, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->Bf, bf);
+ }
+ if (ret == 0) {
+ localIdx = *inOutIdx;
+ if (*inOutIdx < inSz && GetASNTag(input, &localIdx, &tag, inSz)
+ == 0 && tag == ASN_BIT_STRING) {
+ len = 0;
+ ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz);
+ *inOutIdx += len;
+ }
+ }
+ if (ret == 0) {
+ ret = ASNToHexString(input, inOutIdx, (char**)&point, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+
+ /* sanity check that point buffer is not smaller than the expected
+ * size to hold ( 0 4 || Gx || Gy )
+ * where Gx and Gy are each the size of curve->size * 2 */
+ if (ret == 0 && (int)XSTRLEN(point) < (curve->size * 4) + 2) {
+ XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ ret = BUFFER_E;
+ }
+ }
+ if (ret == 0) {
+ #ifndef WOLFSSL_ECC_CURVE_STATIC
+ curve->Gx = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
+ DYNAMIC_TYPE_ECC_BUFFER);
+ curve->Gy = (const char*)XMALLOC(curve->size * 2 + 2, key->heap,
+ DYNAMIC_TYPE_ECC_BUFFER);
+ if (curve->Gx == NULL || curve->Gy == NULL) {
+ XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ ret = MEMORY_E;
+ }
+ #else
+ if (curve->size * 2 + 2 > MAX_ECC_STRING) {
+ WOLFSSL_MSG("curve size is too large to fit in buffer");
+ ret = BUFFER_E;
+ }
+ #endif
+ }
+ if (ret == 0) {
+ char* o = NULL;
+
+ XMEMCPY((char*)curve->Gx, point + 2, curve->size * 2);
+ XMEMCPY((char*)curve->Gy, point + curve->size * 2 + 2,
+ curve->size * 2);
+ ((char*)curve->Gx)[curve->size * 2] = '\0';
+ ((char*)curve->Gy)[curve->size * 2] = '\0';
+ XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ ret = ASNToHexString(input, inOutIdx, &o, inSz,
+ key->heap, DYNAMIC_TYPE_ECC_BUFFER);
+ if (ret == 0)
+ ret = EccKeyParamCopy((char**)&curve->order, o);
+ }
+ if (ret == 0) {
+ curve->cofactor = GetInteger7Bit(input, inOutIdx, inSz);
+
+ #ifndef WOLFSSL_ECC_CURVE_STATIC
+ curve->oid = NULL;
+ #else
+ XMEMSET((void*)curve->oid, 0, sizeof(curve->oid));
+ #endif
+ curve->oidSz = 0;
+ curve->oidSum = 0;
+
+ if (wc_ecc_set_custom_curve(key, curve) < 0) {
+ ret = ASN_PARSE_E;
+ }
+ #ifdef WOLFSSL_CUSTOM_CURVES
+ key->deallocSet = 1;
+ #endif
+ curve = NULL;
+ }
+ if (curve != NULL)
+ wc_ecc_free_curve(curve, key->heap);
+
+ if (ret < 0)
+ return ret;
+#else
+ return ASN_PARSE_E;
+#endif /* WOLFSSL_CUSTOM_CURVES */
+ }
+ else {
+ /* ecc params information */
+ ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz);
+ if (ret != 0)
+ return ret;
+
+ /* get curve id */
+ curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
+ if (curve_id < 0)
+ return ECC_CURVE_OID_E;
+ }
+
+ /* key header */
+ ret = CheckBitString(input, inOutIdx, &length, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ /* This is the raw point data compressed or uncompressed. */
+ if (wc_ecc_import_x963_ex(input + *inOutIdx, length, key,
+ curve_id) != 0) {
+ return ASN_ECC_KEY_E;
+ }
+
+ *inOutIdx += length;
+
+ return 0;
+}
+
+#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT)
+/* build DER formatted ECC key, include optional public key if requested,
+ * return length on success, negative on error */
+static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
+ int pubIn)
{
- byte curve[MAX_ALGO_SZ];
+ byte curve[MAX_ALGO_SZ+2];
byte ver[MAX_VERSION_SZ];
byte seq[MAX_SEQ_SZ];
- int ret;
- int curveSz;
- int verSz;
+ byte *prv = NULL, *pub = NULL;
+ int ret, totalSz, curveSz, verSz;
int privHdrSz = ASN_ECC_HEADER_SZ;
int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ;
- int curveHdrSz = ASN_ECC_CONTEXT_SZ;
- word32 seqSz;
- word32 idx = 0;
- word32 pubSz = ECC_BUFSIZE;
- word32 privSz;
- word32 totalSz;
+
+ word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0;
+ word32 seqSz, privSz, pubSz = ECC_BUFSIZE;
if (key == NULL || output == NULL || inLen == 0)
return BAD_FUNC_ARG;
- ret = wc_ecc_export_x963(key, NULL, &pubSz);
- if (ret != LENGTH_ONLY_E) {
- return ret;
- }
- curveSz = SetCurve(key, curve);
- if (curveSz < 0) {
+ /* curve */
+ curve[curveidx++] = ECC_PREFIX_0;
+ curveidx++ /* to put the size after computation */;
+ curveSz = SetCurve(key, curve+curveidx);
+ if (curveSz < 0)
return curveSz;
- }
+ /* set computed size */
+ curve[1] = (byte)curveSz;
+ curveidx += curveSz;
+ /* private */
privSz = key->dp->size;
+ prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ,
+ key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (prv == NULL) {
+ return MEMORY_E;
+ }
+ prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]);
+ ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz);
+ if (ret < 0) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+ prvidx += privSz;
- verSz = SetMyVersion(1, ver, FALSE);
- if (verSz < 0) {
- return verSz;
+ /* pubIn */
+ if (pubIn) {
+ ret = wc_ecc_export_x963(key, NULL, &pubSz);
+ if (ret != LENGTH_ONLY_E) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ,
+ key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pub == NULL) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return MEMORY_E;
+ }
+
+ pub[pubidx++] = ECC_PREFIX_1;
+ if (pubSz > 128) /* leading zero + extra size byte */
+ pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx);
+ else /* leading zero */
+ pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx);
+
+ /* SetBitString adds leading zero */
+ pubidx += SetBitString(pubSz, 0, pub + pubidx);
+ ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz);
+ if (ret != 0) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+ pubidx += pubSz;
}
- totalSz = verSz + privSz + privHdrSz + curveSz + curveHdrSz +
- pubSz + pubHdrSz + 1; /* plus null byte b4 public */
- seqSz = SetSequence(totalSz, seq);
- totalSz += seqSz;
+ /* make headers */
+ verSz = SetMyVersion(1, ver, FALSE);
+ seqSz = SetSequence(verSz + prvidx + pubidx + curveidx, seq);
- if (totalSz > inLen) {
- return BUFFER_E;
+ totalSz = prvidx + pubidx + curveidx + verSz + seqSz;
+ if (totalSz > (int)inLen) {
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (pubIn) {
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return BAD_FUNC_ARG;
}
- /* write it out */
+ /* write out */
/* seq */
XMEMCPY(output + idx, seq, seqSz);
- idx += seqSz;
+ idx = seqSz;
- /* ver */
+ /* ver */
XMEMCPY(output + idx, ver, verSz);
idx += verSz;
/* private */
- output[idx++] = ASN_OCTET_STRING;
- output[idx++] = (byte)privSz;
- ret = wc_ecc_export_private_only(key, output + idx, &privSz);
+ XMEMCPY(output + idx, prv, prvidx);
+ idx += prvidx;
+ XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ /* curve */
+ XMEMCPY(output + idx, curve, curveidx);
+ idx += curveidx;
+
+ /* pubIn */
+ if (pubIn) {
+ XMEMCPY(output + idx, pub, pubidx);
+ /* idx += pubidx; not used after write, if more data remove comment */
+ XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+
+ return totalSz;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEccKeyDer(key, output, inLen, 1);
+}
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEccKeyDer(key, output, inLen, 0);
+}
+
+#ifdef HAVE_PKCS8
+/* Write only private ecc key to unencrypted PKCS#8 format.
+ *
+ * If output is NULL, places required PKCS#8 buffer size in outLen and
+ * returns LENGTH_ONLY_E.
+ *
+ * return length on success else < 0 */
+int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen)
+{
+ int ret, tmpDerSz;
+ int algoID = 0;
+ word32 oidSz = 0;
+ word32 pkcs8Sz = 0;
+ const byte* curveOID = NULL;
+ byte* tmpDer = NULL;
+
+ if (key == NULL || outLen == NULL)
+ return BAD_FUNC_ARG;
+
+ /* set algoID, get curve OID */
+ algoID = ECDSAk;
+ ret = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz);
+ if (ret < 0)
+ return ret;
+
+ /* temp buffer for plain DER key */
+ tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ if (tmpDer == NULL)
+ return MEMORY_E;
+
+ XMEMSET(tmpDer, 0, ECC_BUFSIZE);
+
+ tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0);
+ if (tmpDerSz < 0) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return tmpDerSz;
+ }
+
+ /* get pkcs8 expected output size */
+ ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID,
+ curveOID, oidSz);
+ if (ret != LENGTH_ONLY_E) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ return ret;
+ }
+
+ if (output == NULL) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ *outLen = pkcs8Sz;
+ return LENGTH_ONLY_E;
+
+ } else if (*outLen < pkcs8Sz) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+ WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key");
+ return BUFFER_E;
+ }
+
+ ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz,
+ algoID, curveOID, oidSz);
if (ret < 0) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
- idx += privSz;
- /* curve */
- output[idx++] = ECC_PREFIX_0;
- output[idx++] = (byte)curveSz;
- XMEMCPY(output + idx, curve, curveSz);
- idx += curveSz;
-
- /* public */
- output[idx++] = ECC_PREFIX_1;
- output[idx++] = (byte)pubSz + ASN_ECC_CONTEXT_SZ + 1; /* plus null byte */
- output[idx++] = ASN_BIT_STRING;
- output[idx++] = (byte)pubSz + 1; /* plus null byte */
- output[idx++] = (byte)0; /* null byte */
- ret = wc_ecc_export_x963(key, output + idx, &pubSz);
- if (ret != 0) {
+ XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+ *outLen = ret;
+ return ret;
+}
+#endif /* HAVE_PKCS8 */
+#endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */
+#endif /* HAVE_ECC */
+
+
+#ifdef HAVE_ED25519
+
+int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx,
+ ed25519_key* key, word32 inSz)
+{
+ word32 oid;
+ int ret, version, length, endKeyIdx, privSz, pubSz;
+ const byte* priv;
+ const byte* pub;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
+ endKeyIdx = *inOutIdx + length;
+
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+ if (version != 0) {
+ WOLFSSL_MSG("Unrecognized version of ED25519 private key");
+ return ASN_PARSE_E;
+ }
+
+ if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0)
+ return ASN_PARSE_E;
+ if (oid != ED25519k)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ }
+ else {
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (privSz != 32)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ endKeyIdx = *inOutIdx;
+ }
+
+ if (endKeyIdx == (int)*inOutIdx) {
+ ret = wc_ed25519_import_private_only(priv, privSz, key);
+ }
+ else {
+ if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
+ inOutIdx, &length, inSz) < 0) {
+ return ASN_PARSE_E;
+ }
+ if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0)
+ return ASN_PARSE_E;
+ pub = input + *inOutIdx;
+ *inOutIdx += pubSz;
+
+ ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key);
+ }
+ if (ret == 0 && endKeyIdx != (int)*inOutIdx)
+ return ASN_PARSE_E;
+
+ return ret;
+}
+
+
+int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx,
+ ed25519_key* key, word32 inSz)
+{
+ int length;
+ int ret;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = SkipObjectId(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+
+ /* key header */
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
return ret;
+
+ /* This is the raw point data compressed or uncompressed. */
+ if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0)
+ return ASN_ECC_KEY_E;
+
+ return 0;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* build DER formatted ED25519 key,
+ * return length on success, negative on error */
+static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen,
+ int pubOut)
+{
+ byte algoArray[MAX_ALGO_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte seq[MAX_SEQ_SZ];
+ int ret;
+ word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0;
+
+ if (key == NULL || output == NULL || inLen == 0)
+ return BAD_FUNC_ARG;
+
+ if (pubOut)
+ pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE;
+ privSz = 2 + 2 + ED25519_KEY_SIZE;
+ algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0);
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq);
+
+ if (seqSz + verSz + algoSz + privSz + pubSz > inLen)
+ return BAD_FUNC_ARG;
+
+ /* write out */
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx = seqSz;
+ /* ver */
+ XMEMCPY(output + idx, ver, verSz);
+ idx += verSz;
+ /* algo */
+ XMEMCPY(output + idx, algoArray, algoSz);
+ idx += algoSz;
+ /* privKey */
+ idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
+ ret = wc_ed25519_export_private_only(key, output + idx, &privSz);
+ if (ret != 0)
+ return ret;
+ idx += privSz;
+ /* pubKey */
+ if (pubOut) {
+ idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED25519_KEY_SIZE, output + idx);
+ ret = wc_ed25519_export_public(key, output + idx, &pubSz);
+ if (ret != 0)
+ return ret;
+ idx += pubSz;
}
- /* idx += pubSz if do more later */
- return totalSz;
+ return idx;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd25519KeyDer(key, output, inLen, 1);
+}
+
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd25519KeyDer(key, output, inLen, 0);
}
#endif /* WOLFSSL_KEY_GEN */
-#endif /* HAVE_ECC */
+#endif /* HAVE_ED25519 */
+#ifdef HAVE_ED448
+
+int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx,
+ ed448_key* key, word32 inSz)
+{
+ word32 oid;
+ int ret, version, length, endKeyIdx, privSz, pubSz;
+ const byte* priv;
+ const byte* pub;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) >= 0) {
+ endKeyIdx = *inOutIdx + length;
+
+ if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
+ return ASN_PARSE_E;
+ if (version != 0) {
+ WOLFSSL_MSG("Unrecognized version of ED448 private key");
+ return ASN_PARSE_E;
+ }
+
+ if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0)
+ return ASN_PARSE_E;
+ if (oid != ED448k)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ }
+ else {
+ if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (privSz != 57)
+ return ASN_PARSE_E;
+
+ priv = input + *inOutIdx;
+ *inOutIdx += privSz;
+ endKeyIdx = *inOutIdx;
+ }
+
+ if (endKeyIdx == (int)*inOutIdx) {
+ ret = wc_ed448_import_private_only(priv, privSz, key);
+ }
+ else {
+ if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
+ inOutIdx, &length, inSz) < 0) {
+ return ASN_PARSE_E;
+ }
+ if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0)
+ return ASN_PARSE_E;
+ pub = input + *inOutIdx;
+ *inOutIdx += pubSz;
+
+ ret = wc_ed448_import_private_key(priv, privSz, pub, pubSz, key);
+ }
+ if (ret == 0 && endKeyIdx != (int)*inOutIdx)
+ return ASN_PARSE_E;
+
+ return ret;
+}
+
+
+int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx,
+ ed448_key* key, word32 inSz)
+{
+ int length;
+ int ret;
+
+ if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
+ return BAD_FUNC_ARG;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+ return ASN_PARSE_E;
+
+ ret = SkipObjectId(input, inOutIdx, inSz);
+ if (ret != 0)
+ return ret;
+
+ /* key header */
+ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ /* This is the raw point data compressed or uncompressed. */
+ if (wc_ed448_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0)
+ return ASN_ECC_KEY_E;
+
+ return 0;
+}
+
+
+#ifdef WOLFSSL_KEY_GEN
+
+/* build DER formatted ED448 key,
+ * return length on success, negative on error */
+static int wc_BuildEd448KeyDer(ed448_key* key, byte* output, word32 inLen,
+ int pubOut)
+{
+ byte algoArray[MAX_ALGO_SZ];
+ byte ver[MAX_VERSION_SZ];
+ byte seq[MAX_SEQ_SZ];
+ int ret;
+ word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0;
+
+ if (key == NULL || output == NULL || inLen == 0)
+ return BAD_FUNC_ARG;
+
+ if (pubOut) {
+ pubSz = 2 + 2 + ED448_PUB_KEY_SIZE;
+ }
+ privSz = 2 + 2 + ED448_KEY_SIZE;
+ algoSz = SetAlgoID(ED448k, algoArray, oidKeyType, 0);
+ verSz = SetMyVersion(0, ver, FALSE);
+ seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq);
+
+ if (seqSz + verSz + algoSz + privSz + pubSz > inLen)
+ return BAD_FUNC_ARG;
+
+ /* write out */
+ /* seq */
+ XMEMCPY(output + idx, seq, seqSz);
+ idx = seqSz;
+ /* ver */
+ XMEMCPY(output + idx, ver, verSz);
+ idx += verSz;
+ /* algo */
+ XMEMCPY(output + idx, algoArray, algoSz);
+ idx += algoSz;
+ /* privKey */
+ idx += SetOctetString(2 + ED448_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED448_KEY_SIZE, output + idx);
+ ret = wc_ed448_export_private_only(key, output + idx, &privSz);
+ if (ret != 0)
+ return ret;
+ idx += privSz;
+ /* pubKey */
+ if (pubOut) {
+ idx += SetExplicit(1, 2 + ED448_PUB_KEY_SIZE, output + idx);
+ idx += SetOctetString(ED448_KEY_SIZE, output + idx);
+ ret = wc_ed448_export_public(key, output + idx, &pubSz);
+ if (ret != 0)
+ return ret;
+ idx += pubSz;
+ }
+
+ return idx;
+}
+
+/* Write a Private ecc key, including public to DER format,
+ * length on success else < 0 */
+int wc_Ed448KeyToDer(ed448_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd448KeyDer(key, output, inLen, 1);
+}
+
+
+
+/* Write only private ecc key to DER format,
+ * length on success else < 0 */
+int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, word32 inLen)
+{
+ return wc_BuildEd448KeyDer(key, output, inLen, 0);
+}
+
+#endif /* WOLFSSL_KEY_GEN */
+
+#endif /* HAVE_ED448 */
#if defined(HAVE_OCSP) || defined(HAVE_CRL)
@@ -6832,46 +16134,47 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen)
static int GetBasicDate(const byte* source, word32* idx, byte* date,
byte* format, int maxIdx)
{
- int length;
+ int ret, length;
+ const byte *datePtr = NULL;
WOLFSSL_ENTER("GetBasicDate");
- *format = source[*idx];
- *idx += 1;
- if (*format != ASN_UTC_TIME && *format != ASN_GENERALIZED_TIME)
- return ASN_TIME_E;
-
- if (GetLength(source, idx, &length, maxIdx) < 0)
- return ASN_PARSE_E;
-
- if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE)
- return ASN_DATE_SZ_E;
+ ret = GetDateInfo(source, idx, &datePtr, format, &length, maxIdx);
+ if (ret < 0)
+ return ret;
- XMEMCPY(date, &source[*idx], length);
- *idx += length;
+ XMEMCPY(date, datePtr, length);
return 0;
}
-#endif
+#endif /* HAVE_OCSP || HAVE_CRL */
#ifdef HAVE_OCSP
-static int GetEnumerated(const byte* input, word32* inOutIdx, int *value)
+static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,
+ int sz)
{
word32 idx = *inOutIdx;
word32 len;
+ byte tag;
WOLFSSL_ENTER("GetEnumerated");
*value = 0;
- if (input[idx++] != ASN_ENUMERATED)
+ if (GetASNTag(input, &idx, &tag, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (tag != ASN_ENUMERATED)
return ASN_PARSE_E;
+ if ((int)idx >= sz)
+ return BUFFER_E;
+
len = input[idx++];
- if (len > 4)
+ if (len > 4 || (int)(len + idx) > sz)
return ASN_PARSE_E;
while (len--) {
@@ -6887,9 +16190,11 @@ static int GetEnumerated(const byte* input, word32* inOutIdx, int *value)
static int DecodeSingleResponse(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size)
{
- word32 idx = *ioIndex, prevIndex, oid;
+ word32 idx = *ioIndex, prevIndex, oid, localIdx;
int length, wrapperSz;
CertStatus* cs = resp->status;
+ int ret;
+ byte tag;
WOLFSSL_ENTER("DecodeSingleResponse");
@@ -6910,45 +16215,27 @@ static int DecodeSingleResponse(byte* source,
if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
/* Skip the hash algorithm */
- if (GetAlgoId(source, &idx, &oid, size) < 0)
+ if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0)
return ASN_PARSE_E;
/* Save reference to the hash of CN */
- if (source[idx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, size) < 0)
- return ASN_PARSE_E;
+ ret = GetOctetString(source, &idx, &length, size);
+ if (ret < 0)
+ return ret;
resp->issuerHash = source + idx;
idx += length;
/* Save reference to the hash of the issuer public key */
- if (source[idx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, size) < 0)
- return ASN_PARSE_E;
+ ret = GetOctetString(source, &idx, &length, size);
+ if (ret < 0)
+ return ret;
resp->issuerKeyHash = source + idx;
idx += length;
- /* Read the serial number, it is handled as a string, not as a
- * proper number. Just XMEMCPY the data over, rather than load it
- * as an mp_int. */
- if (source[idx++] != ASN_INTEGER)
- return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, size) < 0)
+ /* Get serial number */
+ if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0)
return ASN_PARSE_E;
- if (length <= EXTERNAL_SERIAL_SIZE)
- {
- if (source[idx] == 0)
- {
- idx++;
- length--;
- }
- XMEMCPY(cs->serial, source + idx, length);
- cs->serialSz = length;
- }
- else
- {
- return ASN_GETINT_E;
- }
- idx += length;
+
+ if ( idx >= size )
+ return BUFFER_E;
/* CertStatus */
switch (source[idx++])
@@ -6971,27 +16258,66 @@ static int DecodeSingleResponse(byte* source,
return ASN_PARSE_E;
}
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ cs->thisDateAsn = source + idx;
+ localIdx = 0;
+ if (GetDateInfo(cs->thisDateAsn, &localIdx, NULL,
+ (byte*)&cs->thisDateParsed.type,
+ &cs->thisDateParsed.length, size) < 0)
+ return ASN_PARSE_E;
+ XMEMCPY(cs->thisDateParsed.data,
+ cs->thisDateAsn + localIdx - cs->thisDateParsed.length,
+ cs->thisDateParsed.length);
+#endif
if (GetBasicDate(source, &idx, cs->thisDate,
&cs->thisDateFormat, size) < 0)
return ASN_PARSE_E;
+
+#ifndef NO_ASN_TIME
+#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE))
return ASN_BEFORE_DATE_E;
-
+#endif
+#endif
+
/* The following items are optional. Only check for them if there is more
* unprocessed data in the singleResponse wrapper. */
-
+
+ localIdx = idx;
if (((int)(idx - prevIndex) < wrapperSz) &&
- (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)))
+ GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
{
idx++;
if (GetLength(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
+ cs->nextDateAsn = source + idx;
+ localIdx = 0;
+ if (GetDateInfo(cs->nextDateAsn, &localIdx, NULL,
+ (byte*)&cs->nextDateParsed.type,
+ &cs->nextDateParsed.length, size) < 0)
+ return ASN_PARSE_E;
+ XMEMCPY(cs->nextDateParsed.data,
+ cs->nextDateAsn + localIdx - cs->nextDateParsed.length,
+ cs->nextDateParsed.length);
+#endif
if (GetBasicDate(source, &idx, cs->nextDate,
&cs->nextDateFormat, size) < 0)
return ASN_PARSE_E;
+
+#ifndef NO_ASN_TIME
+#ifndef WOLFSSL_NO_OCSP_DATE_CHECK
+ if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER))
+ return ASN_AFTER_DATE_E;
+#endif
+#endif
}
+
+ localIdx = idx;
if (((int)(idx - prevIndex) < wrapperSz) &&
- (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)))
+ GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
{
idx++;
if (GetLength(source, &idx, &length, size) < 0)
@@ -7011,48 +16337,66 @@ static int DecodeOcspRespExtensions(byte* source,
int length;
int ext_bound; /* boundary index for the sequence of extensions */
word32 oid;
+ int ret;
+ byte tag;
WOLFSSL_ENTER("DecodeOcspRespExtensions");
- if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
+ if ((idx + 1) > sz)
+ return BUFFER_E;
+
+ if (GetASNTag(source, &idx, &tag, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
return ASN_PARSE_E;
- if (GetLength(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
+ if (GetLength(source, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(source, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
- if (GetSequence(source, &idx, &length, sz) < 0) return ASN_PARSE_E;
-
ext_bound = idx + length;
while (idx < (word32)ext_bound) {
+ word32 localIdx;
+
if (GetSequence(source, &idx, &length, sz) < 0) {
WOLFSSL_MSG("\tfail: should be a SEQUENCE");
return ASN_PARSE_E;
}
oid = 0;
- if (GetObjectId(source, &idx, &oid, sz) < 0) {
+ if (GetObjectId(source, &idx, &oid, oidOcspType, sz) < 0) {
WOLFSSL_MSG("\tfail: OBJECT ID");
return ASN_PARSE_E;
}
/* check for critical flag */
- if (source[idx] == ASN_BOOLEAN) {
- WOLFSSL_MSG("\tfound optional critical flag, moving past");
- idx += (ASN_BOOL_SIZE + 1);
+ if ((idx + 1) > (word32)sz) {
+ WOLFSSL_MSG("\tfail: malformed buffer");
+ return BUFFER_E;
}
- /* process the extension based on the OID */
- if (source[idx++] != ASN_OCTET_STRING) {
- WOLFSSL_MSG("\tfail: should be an OCTET STRING");
- return ASN_PARSE_E;
+ localIdx = idx;
+ if (GetASNTag(source, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) {
+ WOLFSSL_MSG("\tfound optional critical flag, moving past");
+ ret = GetBoolean(source, &idx, sz);
+ if (ret < 0)
+ return ret;
}
- if (GetLength(source, &idx, &length, sz) < 0) {
- WOLFSSL_MSG("\tfail: extension data length");
- return ASN_PARSE_E;
- }
+ ret = GetOctetString(source, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
if (oid == OCSP_NONCE_OID) {
+ /* get data inside extra OCTET_STRING */
+ ret = GetOctetString(source, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
+
resp->nonce = source + idx;
resp->nonceSz = length;
}
@@ -7068,10 +16412,11 @@ static int DecodeOcspRespExtensions(byte* source,
static int DecodeResponseData(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size)
{
- word32 idx = *ioIndex, prev_idx;
+ word32 idx = *ioIndex, prev_idx, localIdx;
int length;
int version;
- word32 responderId = 0;
+ int ret;
+ byte tag;
WOLFSSL_ENTER("DecodeResponseData");
@@ -7085,49 +16430,64 @@ static int DecodeResponseData(byte* source,
* item isn't an EXPLICIT[0], then set version to zero and move
* onto the next item.
*/
- if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
- {
+ localIdx = idx;
+ if (GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
+ {
idx += 2; /* Eat the value and length */
- if (GetMyVersion(source, &idx, &version) < 0)
+ if (GetMyVersion(source, &idx, &version, size) < 0)
return ASN_PARSE_E;
} else
version = 0;
- responderId = source[idx++];
- if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) ||
- (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)))
+ localIdx = idx;
+ if (GetASNTag(source, &localIdx, &tag, size) == 0 &&
+ ( tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1) ||
+ tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2) ))
{
+ idx++; /* advance past ASN tag */
if (GetLength(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
idx += length;
}
else
return ASN_PARSE_E;
-
+
/* save pointer to the producedAt time */
if (GetBasicDate(source, &idx, resp->producedDate,
&resp->producedDateFormat, size) < 0)
return ASN_PARSE_E;
- if (DecodeSingleResponse(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
+ if ((ret = DecodeSingleResponse(source, &idx, resp, size)) < 0)
+ return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
- if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
+ /*
+ * Check the length of the ResponseData against the current index to
+ * see if there are extensions, they are optional.
+ */
+ if (idx - prev_idx < resp->responseSz)
+ if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0)
+ return ASN_PARSE_E;
*ioIndex = idx;
return 0;
}
+#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
+
static int DecodeCerts(byte* source,
word32* ioIndex, OcspResponse* resp, word32 size)
{
word32 idx = *ioIndex;
+ byte tag;
WOLFSSL_ENTER("DecodeCerts");
- if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
+ if (GetASNTag(source, &idx, &tag, size) < 0)
+ return ASN_PARSE_E;
+
+ if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
{
int length;
@@ -7146,14 +16506,20 @@ static int DecodeCerts(byte* source,
return 0;
}
-static int DecodeBasicOcspResponse(byte* source,
- word32* ioIndex, OcspResponse* resp, word32 size)
+#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
+
+
+static int DecodeBasicOcspResponse(byte* source, word32* ioIndex,
+ OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify)
{
- int length;
+ int length;
word32 idx = *ioIndex;
word32 end_index;
+ int ret;
+ int sigLength;
WOLFSSL_ENTER("DecodeBasicOcspResponse");
+ (void)heap;
if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
@@ -7162,51 +16528,102 @@ static int DecodeBasicOcspResponse(byte* source,
return ASN_INPUT_E;
end_index = idx + length;
- if (DecodeResponseData(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
-
+ if ((ret = DecodeResponseData(source, &idx, resp, size)) < 0)
+ return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
+
/* Get the signature algorithm */
- if (GetAlgoId(source, &idx, &resp->sigOID, size) < 0)
+ if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0)
return ASN_PARSE_E;
- /* Obtain pointer to the start of the signature, and save the size */
- if (source[idx++] == ASN_BIT_STRING)
- {
- int sigLength = 0;
- if (GetLength(source, &idx, &sigLength, size) < 0)
- return ASN_PARSE_E;
- resp->sigSz = sigLength;
- resp->sig = source + idx;
- idx += sigLength;
- }
+ ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL);
+ if (ret != 0)
+ return ret;
+
+ resp->sigSz = sigLength;
+ resp->sig = source + idx;
+ idx += sigLength;
/*
* Check the length of the BasicOcspResponse against the current index to
* see if there are certificates, they are optional.
*/
+#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS
if (idx < end_index)
{
DecodedCert cert;
- int ret;
if (DecodeCerts(source, &idx, resp, size) < 0)
return ASN_PARSE_E;
- InitDecodedCert(&cert, resp->cert, resp->certSz, 0);
- ret = ParseCertRelative(&cert, CA_TYPE, NO_VERIFY, 0);
- if (ret < 0)
+ InitDecodedCert(&cert, resp->cert, resp->certSz, heap);
+
+ /* Don't verify if we don't have access to Cert Manager. */
+ ret = ParseCertRelative(&cert, CERT_TYPE,
+ noVerify ? NO_VERIFY : VERIFY_OCSP, cm);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tOCSP Responder certificate parsing failed");
+ FreeDecodedCert(&cert);
return ret;
+ }
+
+#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
+ if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) {
+ if (XMEMCMP(cert.subjectHash,
+ resp->issuerHash, KEYID_SIZE) == 0) {
+ WOLFSSL_MSG("\tOCSP Response signed by issuer");
+ }
+ else {
+ WOLFSSL_MSG("\tOCSP Responder key usage check failed");
+ #ifdef OPENSSL_EXTRA
+ resp->verifyError = OCSP_BAD_ISSUER;
+ #else
+ FreeDecodedCert(&cert);
+ return BAD_OCSP_RESPONDER;
+ #endif
+ }
+ }
+#endif
+
+ /* ConfirmSignature is blocking here */
+ ret = ConfirmSignature(&cert.sigCtx,
+ resp->response, resp->responseSz,
+ cert.publicKey, cert.pubKeySize, cert.keyOID,
+ resp->sig, resp->sigSz, resp->sigOID, NULL);
- ret = ConfirmSignature(resp->response, resp->responseSz,
- cert.publicKey, cert.pubKeySize, cert.keyOID,
- resp->sig, resp->sigSz, resp->sigOID, NULL);
FreeDecodedCert(&cert);
- if (ret == 0)
- {
+ if (ret != 0) {
+ WOLFSSL_MSG("\tOCSP Confirm signature failed");
+ return ASN_OCSP_CONFIRM_E;
+ }
+ }
+ else
+#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */
+ {
+ Signer* ca;
+ int sigValid = -1;
+
+ #ifndef NO_SKID
+ ca = GetCA(cm, resp->issuerKeyHash);
+ #else
+ ca = GetCA(cm, resp->issuerHash);
+ #endif
+
+ if (ca) {
+ SignatureCtx sigCtx;
+ InitSignatureCtx(&sigCtx, heap, INVALID_DEVID);
+
+ /* ConfirmSignature is blocking here */
+ sigValid = ConfirmSignature(&sigCtx, resp->response,
+ resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID,
+ resp->sig, resp->sigSz, resp->sigOID, NULL);
+ }
+ if (ca == NULL || sigValid != 0) {
WOLFSSL_MSG("\tOCSP Confirm signature failed");
return ASN_OCSP_CONFIRM_E;
}
+
+ (void)noVerify;
}
*ioIndex = idx;
@@ -7219,39 +16636,34 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status,
{
WOLFSSL_ENTER("InitOcspResponse");
+ XMEMSET(status, 0, sizeof(CertStatus));
+ XMEMSET(resp, 0, sizeof(OcspResponse));
+
resp->responseStatus = -1;
- resp->response = NULL;
- resp->responseSz = 0;
- resp->producedDateFormat = 0;
- resp->issuerHash = NULL;
- resp->issuerKeyHash = NULL;
- resp->sig = NULL;
- resp->sigSz = 0;
- resp->sigOID = 0;
- resp->status = status;
- resp->nonce = NULL;
- resp->nonceSz = 0;
- resp->source = source;
- resp->maxIdx = inSz;
+ resp->status = status;
+ resp->source = source;
+ resp->maxIdx = inSz;
}
-int OcspResponseDecode(OcspResponse* resp)
+int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify)
{
+ int ret;
int length = 0;
word32 idx = 0;
byte* source = resp->source;
word32 size = resp->maxIdx;
word32 oid;
+ byte tag;
WOLFSSL_ENTER("OcspResponseDecode");
/* peel the outer SEQUENCE wrapper */
if (GetSequence(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
-
+
/* First get the responseStatus, an ENUMERATED */
- if (GetEnumerated(source, &idx, &resp->responseStatus) < 0)
+ if (GetEnumerated(source, &idx, &resp->responseStatus, size) < 0)
return ASN_PARSE_E;
if (resp->responseStatus != OCSP_SUCCESSFUL)
@@ -7260,7 +16672,9 @@ int OcspResponseDecode(OcspResponse* resp)
/* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */
if (idx >= size)
return ASN_INPUT_E;
- if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
+ if (GetASNTag(source, &idx, &tag, size) < 0)
+ return ASN_PARSE_E;
+ if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC))
return ASN_PARSE_E;
if (GetLength(source, &idx, &length, size) < 0)
return ASN_PARSE_E;
@@ -7270,77 +16684,72 @@ int OcspResponseDecode(OcspResponse* resp)
return ASN_PARSE_E;
/* Check ObjectID for the resposeBytes */
- if (GetObjectId(source, &idx, &oid, size) < 0)
+ if (GetObjectId(source, &idx, &oid, oidOcspType, size) < 0)
return ASN_PARSE_E;
if (oid != OCSP_BASIC_OID)
return ASN_PARSE_E;
- if (source[idx++] != ASN_OCTET_STRING)
- return ASN_PARSE_E;
+ ret = GetOctetString(source, &idx, &length, size);
+ if (ret < 0)
+ return ret;
- if (GetLength(source, &idx, &length, size) < 0)
- return ASN_PARSE_E;
+ ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify);
+ if (ret < 0)
+ return ret;
- if (DecodeBasicOcspResponse(source, &idx, resp, size) < 0)
- return ASN_PARSE_E;
-
return 0;
}
-static word32 SetOcspReqExtensions(word32 extSz, byte* output,
- const byte* nonce, word32 nonceSz)
+word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size)
{
- static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+ const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
0x30, 0x01, 0x02 };
byte seqArray[5][MAX_SEQ_SZ];
- word32 seqSz[5], totalSz;
+ word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId);
WOLFSSL_ENTER("SetOcspReqExtensions");
- if (nonce == NULL || nonceSz == 0) return 0;
-
- seqArray[0][0] = ASN_OCTET_STRING;
- seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]);
+ if (!req || !output || !req->nonceSz)
+ return 0;
+
+ totalSz += req->nonceSz;
+ totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]);
+ totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]);
+ totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]);
+ totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]);
+ totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]);
- seqArray[1][0] = ASN_OBJECT_ID;
- seqSz[1] = 1 + SetLength(sizeof(NonceObjId), &seqArray[1][1]);
+ if (totalSz > size)
+ return 0;
- totalSz = seqSz[0] + seqSz[1] + nonceSz + (word32)sizeof(NonceObjId);
+ totalSz = 0;
- seqSz[2] = SetSequence(totalSz, seqArray[2]);
- totalSz += seqSz[2];
+ XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
+ totalSz += seqSz[4];
- seqSz[3] = SetSequence(totalSz, seqArray[3]);
+ XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
totalSz += seqSz[3];
- seqArray[4][0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2);
- seqSz[4] = 1 + SetLength(totalSz, &seqArray[4][1]);
- totalSz += seqSz[4];
+ XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
+ totalSz += seqSz[2];
- if (totalSz < extSz)
- {
- totalSz = 0;
- XMEMCPY(output + totalSz, seqArray[4], seqSz[4]);
- totalSz += seqSz[4];
- XMEMCPY(output + totalSz, seqArray[3], seqSz[3]);
- totalSz += seqSz[3];
- XMEMCPY(output + totalSz, seqArray[2], seqSz[2]);
- totalSz += seqSz[2];
- XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
- totalSz += seqSz[1];
- XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
- totalSz += (word32)sizeof(NonceObjId);
- XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
- totalSz += seqSz[0];
- XMEMCPY(output + totalSz, nonce, nonceSz);
- totalSz += nonceSz;
- }
+ XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId));
+ totalSz += (word32)sizeof(NonceObjId);
+
+ XMEMCPY(output + totalSz, seqArray[1], seqSz[1]);
+ totalSz += seqSz[1];
+
+ XMEMCPY(output + totalSz, seqArray[0], seqSz[0]);
+ totalSz += seqSz[0];
+
+ XMEMCPY(output + totalSz, req->nonce, req->nonceSz);
+ totalSz += req->nonceSz;
return totalSz;
}
-int EncodeOcspRequest(OcspRequest* req)
+int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
{
byte seqArray[5][MAX_SEQ_SZ];
/* The ASN.1 of the OCSP Request is an onion of sequences */
@@ -7349,66 +16758,65 @@ int EncodeOcspRequest(OcspRequest* req)
byte issuerKeyArray[MAX_ENCODED_DIG_SZ];
byte snArray[MAX_SN_SZ];
byte extArray[MAX_OCSP_EXT_SZ];
- byte* output = req->dest;
- word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz;
- int i;
+ word32 seqSz[5], algoSz, issuerSz, issuerKeySz, extSz, totalSz;
+ int i, snSz;
WOLFSSL_ENTER("EncodeOcspRequest");
#ifdef NO_SHA
- algoSz = SetAlgoID(SHA256h, algoArray, hashType, 0);
+ algoSz = SetAlgoID(SHA256h, algoArray, oidHashType, 0);
#else
- algoSz = SetAlgoID(SHAh, algoArray, hashType, 0);
+ algoSz = SetAlgoID(SHAh, algoArray, oidHashType, 0);
#endif
- req->issuerHash = req->cert->issuerHash;
- issuerSz = SetDigest(req->cert->issuerHash, KEYID_SIZE, issuerArray);
-
- req->issuerKeyHash = req->cert->issuerKeyHash;
- issuerKeySz = SetDigest(req->cert->issuerKeyHash,
- KEYID_SIZE, issuerKeyArray);
-
- req->serial = req->cert->serial;
- req->serialSz = req->cert->serialSz;
- snSz = SetSerialNumber(req->cert->serial, req->cert->serialSz, snArray);
-
- extSz = 0;
- if (req->useNonce) {
- RNG rng;
- if (wc_InitRng(&rng) != 0) {
- WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
- } else {
- if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
- WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
- else {
- req->nonceSz = MAX_OCSP_NONCE_SZ;
- extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray,
- req->nonce, req->nonceSz);
- }
- wc_FreeRng(&rng);
- }
+ issuerSz = SetDigest(req->issuerHash, KEYID_SIZE, issuerArray);
+ issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE, issuerKeyArray);
+ snSz = SetSerialNumber(req->serial, req->serialSz, snArray,
+ MAX_SN_SZ, MAX_SN_SZ);
+ extSz = 0;
+
+ if (snSz < 0)
+ return snSz;
+
+ if (req->nonceSz) {
+ /* TLS Extensions use this function too - put extensions after
+ * ASN.1: Context Specific [2].
+ */
+ extSz = EncodeOcspRequestExtensions(req, extArray + 2,
+ OCSP_NONCE_EXT_SZ);
+ extSz += SetExplicit(2, extSz, extArray);
}
totalSz = algoSz + issuerSz + issuerKeySz + snSz;
-
for (i = 4; i >= 0; i--) {
seqSz[i] = SetSequence(totalSz, seqArray[i]);
totalSz += seqSz[i];
if (i == 2) totalSz += extSz;
}
+
+ if (output == NULL)
+ return totalSz;
+ if (totalSz > size)
+ return BUFFER_E;
+
totalSz = 0;
for (i = 0; i < 5; i++) {
XMEMCPY(output + totalSz, seqArray[i], seqSz[i]);
totalSz += seqSz[i];
}
+
XMEMCPY(output + totalSz, algoArray, algoSz);
totalSz += algoSz;
+
XMEMCPY(output + totalSz, issuerArray, issuerSz);
totalSz += issuerSz;
+
XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz);
totalSz += issuerKeySz;
+
XMEMCPY(output + totalSz, snArray, snSz);
totalSz += snSz;
+
if (extSz != 0) {
XMEMCPY(output + totalSz, extArray, extSz);
totalSz += extSz;
@@ -7418,19 +16826,91 @@ int EncodeOcspRequest(OcspRequest* req)
}
-void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
- byte* dest, word32 destSz)
+int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce,
+ void* heap)
{
+ int ret;
+
WOLFSSL_ENTER("InitOcspRequest");
- req->cert = cert;
- req->useNonce = useNonce;
- req->nonceSz = 0;
- req->issuerHash = NULL;
- req->issuerKeyHash = NULL;
- req->serial = NULL;
- req->dest = dest;
- req->destSz = destSz;
+ if (req == NULL)
+ return BAD_FUNC_ARG;
+
+ ForceZero(req, sizeof(OcspRequest));
+ req->heap = heap;
+
+ if (cert) {
+ XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE);
+ XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE);
+
+ req->serial = (byte*)XMALLOC(cert->serialSz, req->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+ if (req->serial == NULL)
+ return MEMORY_E;
+
+ XMEMCPY(req->serial, cert->serial, cert->serialSz);
+ req->serialSz = cert->serialSz;
+
+ if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
+ req->url = (byte*)XMALLOC(cert->extAuthInfoSz + 1, req->heap,
+ DYNAMIC_TYPE_OCSP_REQUEST);
+ if (req->url == NULL) {
+ XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP);
+ return MEMORY_E;
+ }
+
+ XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz);
+ req->urlSz = cert->extAuthInfoSz;
+ req->url[req->urlSz] = 0;
+ }
+ }
+
+ if (useNonce) {
+ WC_RNG rng;
+
+ #ifndef HAVE_FIPS
+ ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID);
+ #else
+ ret = wc_InitRng(&rng);
+ #endif
+ if (ret != 0) {
+ WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce.");
+ } else {
+ if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0)
+ WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce.");
+ else
+ req->nonceSz = MAX_OCSP_NONCE_SZ;
+
+ wc_FreeRng(&rng);
+ }
+ }
+
+ return 0;
+}
+
+void FreeOcspRequest(OcspRequest* req)
+{
+ WOLFSSL_ENTER("FreeOcspRequest");
+
+ if (req) {
+ if (req->serial)
+ XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ req->serial = NULL;
+
+#ifdef OPENSSL_EXTRA
+ if (req->serialInt) {
+ if (req->serialInt->isDynamic) {
+ XFREE(req->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ XFREE(req->serialInt, NULL, DYNAMIC_TYPE_OPENSSL);
+ }
+ req->serialInt = NULL;
+#endif
+
+ if (req->url)
+ XFREE(req->url, req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
+ req->url = NULL;
+ }
}
@@ -7454,14 +16934,18 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
/* Nonces are not critical. The responder may not necessarily add
* the nonce to the response. */
- if (req->useNonce && resp->nonceSz != 0) {
+ if (req->nonceSz
+#ifndef WOLFSSL_FORCE_OCSP_NONCE_CHECK
+ && resp->nonceSz != 0
+#endif
+ ) {
cmp = req->nonceSz - resp->nonceSz;
if (cmp != 0)
{
WOLFSSL_MSG("\tnonceSz mismatch");
return cmp;
}
-
+
cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz);
if (cmp != 0)
{
@@ -7501,20 +16985,22 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
return 0;
}
-#endif
+#endif /* HAVE_OCSP */
-/* store SHA hash of NAME */
-WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
+/* store WC_SHA hash of NAME */
+int GetNameHash(const byte* source, word32* idx, byte* hash,
int maxIdx)
{
int length; /* length of all distinguished names */
int ret;
word32 dummy;
+ byte tag;
WOLFSSL_ENTER("GetNameHash");
- if (source[*idx] == ASN_OBJECT_ID) {
+ dummy = *idx;
+ if (GetASNTag(source, &dummy, &tag, maxIdx) == 0 && tag == ASN_OBJECT_ID) {
WOLFSSL_MSG("Trying optional prefix...");
if (GetLength(source, idx, &length, maxIdx) < 0)
@@ -7531,11 +17017,7 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
if (GetSequence(source, idx, &length, maxIdx) < 0)
return ASN_PARSE_E;
-#ifdef NO_SHA
- ret = wc_Sha256Hash(source + dummy, length + *idx - dummy, hash);
-#else
- ret = wc_ShaHash(source + dummy, length + *idx - dummy, hash);
-#endif
+ ret = CalcHashId(source + dummy, length + *idx - dummy, hash);
*idx += length;
@@ -7546,16 +17028,15 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
#ifdef HAVE_CRL
/* initialize decoded CRL */
-void InitDecodedCRL(DecodedCRL* dcrl)
+void InitDecodedCRL(DecodedCRL* dcrl, void* heap)
{
WOLFSSL_MSG("InitDecodedCRL");
- dcrl->certBegin = 0;
- dcrl->sigIndex = 0;
- dcrl->sigLength = 0;
- dcrl->signatureOID = 0;
- dcrl->certs = NULL;
- dcrl->totalCerts = 0;
+ XMEMSET(dcrl, 0, sizeof(DecodedCRL));
+ dcrl->heap = heap;
+ #ifdef WOLFSSL_HEAP_TEST
+ dcrl->heap = (void*)WOLFSSL_HEAP_TEST;
+ #endif
}
@@ -7568,7 +17049,7 @@ void FreeDecodedCRL(DecodedCRL* dcrl)
while(tmp) {
RevokedCert* next = tmp->next;
- XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
+ XFREE(tmp, dcrl->heap, DYNAMIC_TYPE_REVOKED);
tmp = next;
}
}
@@ -7578,7 +17059,7 @@ void FreeDecodedCRL(DecodedCRL* dcrl)
static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
int maxIdx)
{
- int len;
+ int ret, len;
word32 end;
byte b;
RevokedCert* rc;
@@ -7590,56 +17071,33 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
end = *idx + len;
- /* get serial number */
- b = buff[*idx];
- *idx += 1;
-
- if (b != ASN_INTEGER) {
- WOLFSSL_MSG("Expecting Integer");
- return ASN_PARSE_E;
- }
-
- if (GetLength(buff, idx, &len, maxIdx) < 0)
- return ASN_PARSE_E;
-
- if (len > EXTERNAL_SERIAL_SIZE) {
- WOLFSSL_MSG("Serial Size too big");
- return ASN_PARSE_E;
- }
-
- rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), NULL, DYNAMIC_TYPE_CRL);
+ rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap,
+ DYNAMIC_TYPE_REVOKED);
if (rc == NULL) {
WOLFSSL_MSG("Alloc Revoked Cert failed");
return MEMORY_E;
}
- XMEMCPY(rc->serialNumber, &buff[*idx], len);
- rc->serialSz = len;
+ if (GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz,
+ maxIdx) < 0) {
+ XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED);
+ return ASN_PARSE_E;
+ }
/* add to list */
rc->next = dcrl->certs;
dcrl->certs = rc;
dcrl->totalCerts++;
- *idx += len;
-
/* get date */
- b = buff[*idx];
- *idx += 1;
-
- if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) {
+ ret = GetDateInfo(buff, idx, NULL, &b, NULL, maxIdx);
+ if (ret < 0) {
WOLFSSL_MSG("Expecting Date");
- return ASN_PARSE_E;
+ return ret;
}
- if (GetLength(buff, idx, &len, maxIdx) < 0)
- return ASN_PARSE_E;
-
- /* skip for now */
- *idx += len;
-
- if (*idx != end) /* skip extensions */
- *idx = end;
+ /* skip extensions */
+ *idx = end;
return 0;
}
@@ -7650,29 +17108,244 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
int maxIdx)
{
int length;
- byte b;
+ int ret;
WOLFSSL_ENTER("GetCRL_Signature");
- b = source[*idx];
- *idx += 1;
- if (b != ASN_BIT_STRING)
- return ASN_BITSTR_E;
+ ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL);
+ if (ret != 0)
+ return ret;
+ dcrl->sigLength = length;
- if (GetLength(source, idx, &length, maxIdx) < 0)
+ dcrl->signature = (byte*)&source[*idx];
+ *idx += dcrl->sigLength;
+
+ return 0;
+}
+
+int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned,
+ word32 tbsSz, const byte* signature, word32 sigSz,
+ word32 signatureOID, Signer *ca, void* heap)
+{
+ /* try to confirm/verify signature */
+#ifndef IGNORE_KEY_EXTENSIONS
+ if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) {
+ WOLFSSL_MSG("CA cannot sign CRLs");
+ return ASN_CRL_NO_SIGNER_E;
+ }
+#endif /* IGNORE_KEY_EXTENSIONS */
+
+ InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
+ if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey,
+ ca->pubKeySize, ca->keyOID, signature, sigSz,
+ signatureOID, NULL) != 0) {
+ WOLFSSL_MSG("CRL Confirm signature failed");
+ return ASN_CRL_CONFIRM_E;
+ }
+
+ return 0;
+}
+
+
+static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf,
+ word32* inOutIdx, int sz)
+{
+ word32 oid, dateIdx, idx, checkIdx;
+ int version, doNextDate = 1;
+ byte tag;
+
+ if (dcrl == NULL || inOutIdx == NULL || buf == NULL) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* may have version */
+ idx = *inOutIdx;
+
+ checkIdx = idx;
+ if (GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag == ASN_INTEGER) {
+ if (GetMyVersion(buf, &idx, &version, sz) < 0)
+ return ASN_PARSE_E;
+ }
+
+ if (GetAlgoId(buf, &idx, &oid, oidIgnoreType, sz) < 0)
return ASN_PARSE_E;
- dcrl->sigLength = length;
+ if (GetNameHash(buf, &idx, dcrl->issuerHash, sz) < 0)
+ return ASN_PARSE_E;
- b = source[*idx];
- *idx += 1;
- if (b != 0x00)
- return ASN_EXPECT_0_E;
+ if (GetBasicDate(buf, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
+ return ASN_PARSE_E;
- dcrl->sigLength--;
- dcrl->signature = (byte*)&source[*idx];
+ dateIdx = idx;
- *idx += dcrl->sigLength;
+ if (GetBasicDate(buf, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
+ {
+#ifndef WOLFSSL_NO_CRL_NEXT_DATE
+ (void)dateIdx;
+ return ASN_PARSE_E;
+#else
+ dcrl->nextDateFormat = ASN_OTHER_TYPE; /* skip flag */
+ doNextDate = 0;
+ idx = dateIdx;
+#endif
+ }
+
+ if (doNextDate) {
+#ifndef NO_ASN_TIME
+ if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
+ WOLFSSL_MSG("CRL after date is no longer valid");
+ return ASN_AFTER_DATE_E;
+ }
+#endif
+ }
+
+ checkIdx = idx;
+ if (idx != dcrl->sigIndex &&
+ GetASNTag(buf, &checkIdx, &tag, sz) == 0 && tag != CRL_EXTENSIONS) {
+
+ int len;
+
+ if (GetSequence(buf, &idx, &len, sz) < 0)
+ return ASN_PARSE_E;
+ len += idx;
+
+ while (idx < (word32)len) {
+ if (GetRevoked(buf, &idx, dcrl, len) < 0)
+ return ASN_PARSE_E;
+ }
+ }
+
+ *inOutIdx = idx;
+
+ return 0;
+}
+
+
+#ifndef NO_SKID
+static int ParseCRL_AuthKeyIdExt(const byte* input, int sz, DecodedCRL* dcrl)
+{
+ word32 idx = 0;
+ int length = 0, ret = 0;
+ byte tag;
+
+ WOLFSSL_ENTER("ParseCRL_AuthKeyIdExt");
+
+ if (GetSequence(input, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE\n");
+ return ASN_PARSE_E;
+ }
+
+ if (GetASNTag(input, &idx, &tag, sz) < 0) {
+ return ASN_PARSE_E;
+ }
+
+ if (tag != (ASN_CONTEXT_SPECIFIC | 0)) {
+ WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n");
+ return 0;
+ }
+
+ if (GetLength(input, &idx, &length, sz) <= 0) {
+ WOLFSSL_MSG("\tfail: extension data length");
+ return ASN_PARSE_E;
+ }
+
+ dcrl->extAuthKeyIdSet = 1;
+ if (length == KEYID_SIZE) {
+ XMEMCPY(dcrl->extAuthKeyId, input + idx, length);
+ }
+ else {
+ ret = CalcHashId(input + idx, length, dcrl->extAuthKeyId);
+ }
+
+ return ret;
+}
+#endif
+
+
+static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf,
+ word32* inOutIdx, word32 sz)
+{
+ int length;
+ word32 idx;
+ word32 ext_bound; /* boundary index for the sequence of extensions */
+ word32 oid;
+ byte tag;
+
+ WOLFSSL_ENTER("ParseCRL_Extensions");
+ (void)dcrl;
+
+ if (inOutIdx == NULL)
+ return BAD_FUNC_ARG;
+
+ idx = *inOutIdx;
+
+ /* CRL Extensions are optional */
+ if ((idx + 1) > sz)
+ return 0;
+
+ /* CRL Extensions are optional */
+ if (GetASNTag(buf, &idx, &tag, sz) < 0)
+ return 0;
+
+ /* CRL Extensions are optional */
+ if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
+ return 0;
+
+ if (GetLength(buf, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ if (GetSequence(buf, &idx, &length, sz) < 0)
+ return ASN_PARSE_E;
+
+ ext_bound = idx + length;
+
+ while (idx < (word32)ext_bound) {
+ word32 localIdx;
+ int ret;
+
+ if (GetSequence(buf, &idx, &length, sz) < 0) {
+ WOLFSSL_MSG("\tfail: should be a SEQUENCE");
+ return ASN_PARSE_E;
+ }
+
+ oid = 0;
+ if (GetObjectId(buf, &idx, &oid, oidCrlExtType, sz) < 0) {
+ WOLFSSL_MSG("\tfail: OBJECT ID");
+ return ASN_PARSE_E;
+ }
+
+ /* check for critical flag */
+ if ((idx + 1) > (word32)sz) {
+ WOLFSSL_MSG("\tfail: malformed buffer");
+ return BUFFER_E;
+ }
+
+ localIdx = idx;
+ if (GetASNTag(buf, &localIdx, &tag, sz) == 0 && tag == ASN_BOOLEAN) {
+ WOLFSSL_MSG("\tfound optional critical flag, moving past");
+ ret = GetBoolean(buf, &idx, sz);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = GetOctetString(buf, &idx, &length, sz);
+ if (ret < 0)
+ return ret;
+
+ if (oid == AUTH_KEY_OID) {
+ #ifndef NO_SKID
+ ret = ParseCRL_AuthKeyIdExt(buf + idx, length, dcrl);
+ if (ret < 0) {
+ WOLFSSL_MSG("\tcouldn't parse AuthKeyId extension");
+ return ret;
+ }
+ #endif
+ }
+
+ idx += length;
+ }
+
+ *inOutIdx = idx;
return 0;
}
@@ -7681,15 +17354,16 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl,
/* prase crl buffer into decoded state, 0 on success */
int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
{
- int version, len;
- word32 oid, idx = 0;
- Signer* ca = NULL;
+ int len;
+ word32 idx = 0;
+ Signer* ca = NULL;
+ SignatureCtx sigCtx;
WOLFSSL_MSG("ParseCRL");
/* raw crl hash */
/* hash here if needed for optimized comparisons
- * Sha sha;
+ * wc_Sha sha;
* wc_InitSha(&sha);
* wc_ShaUpdate(&sha, buff, sz);
* wc_ShaFinal(&sha, dcrl->crlHash); */
@@ -7698,98 +17372,154 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
return ASN_PARSE_E;
dcrl->certBegin = idx;
+ /* Normalize sz for the length inside the outer sequence. */
+ sz = len + idx;
if (GetSequence(buff, &idx, &len, sz) < 0)
return ASN_PARSE_E;
dcrl->sigIndex = len + idx;
- /* may have version */
- if (buff[idx] == ASN_INTEGER) {
- if (GetMyVersion(buff, &idx, &version) < 0)
- return ASN_PARSE_E;
- }
-
- if (GetAlgoId(buff, &idx, &oid, sz) < 0)
+ if (ParseCRL_CertList(dcrl, buff, &idx, idx + len) < 0)
return ASN_PARSE_E;
- if (GetNameHash(buff, &idx, dcrl->issuerHash, sz) < 0)
+ if (ParseCRL_Extensions(dcrl, buff, &idx, idx + len) < 0)
return ASN_PARSE_E;
- if (GetBasicDate(buff, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
+ idx = dcrl->sigIndex;
+
+ if (GetAlgoId(buff, &idx, &dcrl->signatureOID, oidSigType, sz) < 0)
return ASN_PARSE_E;
- if (GetBasicDate(buff, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0)
+ if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
return ASN_PARSE_E;
- if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) {
- WOLFSSL_MSG("CRL after date is no longer valid");
- return ASN_AFTER_DATE_E;
+ /* openssl doesn't add skid by default for CRLs cause firefox chokes
+ if experiencing issues uncomment NO_SKID define in CRL section of
+ wolfssl/wolfcrypt/settings.h */
+#ifndef NO_SKID
+ if (dcrl->extAuthKeyIdSet) {
+ ca = GetCA(cm, dcrl->extAuthKeyId); /* more unique than issuerHash */
+ }
+ if (ca != NULL && XMEMCMP(dcrl->issuerHash, ca->subjectNameHash,
+ KEYID_SIZE) != 0) {
+ ca = NULL;
+ }
+ if (ca == NULL) {
+ ca = GetCAByName(cm, dcrl->issuerHash); /* last resort */
+ /* If AKID is available then this CA doesn't have the public
+ * key required */
+ if (ca && dcrl->extAuthKeyIdSet) {
+ WOLFSSL_MSG("CA SKID doesn't match AKID");
+ ca = NULL;
+ }
}
+#else
+ ca = GetCA(cm, dcrl->issuerHash);
+#endif /* !NO_SKID */
+ WOLFSSL_MSG("About to verify CRL signature");
- if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) {
- if (GetSequence(buff, &idx, &len, sz) < 0)
- return ASN_PARSE_E;
+ if (ca == NULL) {
+ WOLFSSL_MSG("Did NOT find CRL issuer CA");
+ return ASN_CRL_NO_SIGNER_E;
+ }
- len += idx;
+ WOLFSSL_MSG("Found CRL issuer CA");
+ return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin,
+ dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength,
+ dcrl->signatureOID, ca, dcrl->heap);
+}
- while (idx < (word32)len) {
- if (GetRevoked(buff, &idx, dcrl, sz) < 0)
- return ASN_PARSE_E;
+#endif /* HAVE_CRL */
+
+
+
+#ifdef WOLFSSL_CERT_PIV
+
+int wc_ParseCertPIV(wc_CertPIV* piv, const byte* buf, word32 totalSz)
+{
+ int length = 0;
+ word32 idx = 0;
+
+ WOLFSSL_ENTER("wc_ParseCertPIV");
+
+ if (piv == NULL || buf == NULL || totalSz == 0)
+ return BAD_FUNC_ARG;
+
+ XMEMSET(piv, 0, sizeof(wc_CertPIV));
+
+ /* Detect Identiv PIV (with 0x0A, 0x0B and 0x0C sections) */
+ /* Certificate (0A 82 05FA) */
+ if (GetASNHeader(buf, ASN_PIV_CERT, &idx, &length, totalSz) >= 0) {
+ /* Identiv Type PIV card */
+ piv->isIdentiv = 1;
+
+ piv->cert = &buf[idx];
+ piv->certSz = length;
+ idx += length;
+
+ /* Nonce (0B 14) */
+ if (GetASNHeader(buf, ASN_PIV_NONCE, &idx, &length, totalSz) >= 0) {
+ piv->nonce = &buf[idx];
+ piv->nonceSz = length;
+ idx += length;
}
- }
- if (idx != dcrl->sigIndex)
- idx = dcrl->sigIndex; /* skip extensions */
+ /* Signed Nonce (0C 82 0100) */
+ if (GetASNHeader(buf, ASN_PIV_SIGNED_NONCE, &idx, &length, totalSz) >= 0) {
+ piv->signedNonce = &buf[idx];
+ piv->signedNonceSz = length;
+ }
- if (GetAlgoId(buff, &idx, &dcrl->signatureOID, sz) < 0)
- return ASN_PARSE_E;
+ idx = 0;
+ buf = piv->cert;
+ totalSz = piv->certSz;
+ }
- if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0)
+ /* Certificate Buffer Total Size (53 82 05F6) */
+ if (GetASNHeader(buf, ASN_APPLICATION | ASN_PRINTABLE_STRING, &idx,
+ &length, totalSz) < 0) {
return ASN_PARSE_E;
+ }
+ /* PIV Certificate (70 82 05ED) */
+ if (GetASNHeader(buf, ASN_PIV_TAG_CERT, &idx, &length,
+ totalSz) < 0) {
+ return ASN_PARSE_E;
+ }
- /* openssl doesn't add skid by default for CRLs cause firefox chokes
- we're not assuming it's available yet */
- #if !defined(NO_SKID) && defined(CRL_SKID_READY)
- if (dcrl->extAuthKeyIdSet)
- ca = GetCA(cm, dcrl->extAuthKeyId);
- if (ca == NULL)
- ca = GetCAByName(cm, dcrl->issuerHash);
- #else /* NO_SKID */
- ca = GetCA(cm, dcrl->issuerHash);
- #endif /* NO_SKID */
- WOLFSSL_MSG("About to verify CRL signature");
+ /* Capture certificate buffer pointer and length */
+ piv->cert = &buf[idx];
+ piv->certSz = length;
+ idx += length;
- if (ca) {
- WOLFSSL_MSG("Found CRL issuer CA");
- /* try to confirm/verify signature */
- #ifndef IGNORE_KEY_EXTENSIONS
- if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) {
- WOLFSSL_MSG("CA cannot sign CRLs");
- return ASN_CRL_NO_SIGNER_E;
- }
- #endif /* IGNORE_KEY_EXTENSIONS */
- if (!ConfirmSignature(buff + dcrl->certBegin,
- dcrl->sigIndex - dcrl->certBegin,
- ca->publicKey, ca->pubKeySize, ca->keyOID,
- dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) {
- WOLFSSL_MSG("CRL Confirm signature failed");
- return ASN_CRL_CONFIRM_E;
+ /* PIV Certificate Info (71 01 00) */
+ if (GetASNHeader(buf, ASN_PIV_TAG_CERT_INFO, &idx, &length,
+ totalSz) >= 0) {
+ if (length >= 1) {
+ piv->compression = (buf[idx] & ASN_PIV_CERT_INFO_COMPRESSED);
+ piv->isX509 = (buf[idx] & ASN_PIV_CERT_INFO_ISX509);
}
+ idx += length;
}
- else {
- WOLFSSL_MSG("Did NOT find CRL issuer CA");
- return ASN_CRL_NO_SIGNER_E;
+
+ /* PIV Error Detection (FE 00) */
+ if (GetASNHeader(buf, ASN_PIV_TAG_ERR_DET, &idx, &length,
+ totalSz) >= 0) {
+ piv->certErrDet = &buf[idx];
+ piv->certErrDetSz = length;
+ idx += length;
}
return 0;
}
-#endif /* HAVE_CRL */
-#endif
+#endif /* WOLFSSL_CERT_PIV */
-#ifdef WOLFSSL_SEP
+#undef ERROR_OUT
+#endif /* !NO_ASN */
-#endif /* WOLFSSL_SEP */
+#ifdef WOLFSSL_SEP
+
+#endif /* WOLFSSL_SEP */