diff --git a/certs/1024/client-keyPub.der b/certs/1024/client-keyPub.der new file mode 100644 index 000000000..a5c1817d9 Binary files /dev/null and b/certs/1024/client-keyPub.der differ diff --git a/certs/client-keyPub.der b/certs/client-keyPub.der new file mode 100644 index 000000000..b27f0e9bb Binary files /dev/null and b/certs/client-keyPub.der differ diff --git a/certs/ecc-keyPub.der b/certs/ecc-keyPub.der new file mode 100644 index 000000000..91aa79bee Binary files /dev/null and b/certs/ecc-keyPub.der differ diff --git a/configure.ac b/configure.ac index 3e296562e..d094b0fa2 100644 --- a/configure.ac +++ b/configure.ac @@ -226,7 +226,7 @@ AC_ARG_ENABLE([bump], if test "$ENABLED_BUMP" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DOPENSSL_EXTRA -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT" + AM_CFLAGS="$AM_CFLAGS -DLARGE_STATIC_BUFFERS -DWOLFSSL_CERT_GEN -DWOLFSSL_KEY_GEN -DHUGE_SESSION_CACHE -DOPENSSL_EXTRA -DFP_MAX_BITS=8192 -DWOLFSSL_DER_LOAD -DWOLFSSL_ALT_NAMES -DWOLFSSL_TEST_CERT -DWOLFSSL_CERT_EXT" fi ENABLED_SLOWMATH="yes" @@ -638,6 +638,23 @@ then fi +# CERT REQUEST EXTENSION +AC_ARG_ENABLE([certext], + [ --enable-certext Enable cert request extensions (default: disabled)], + [ ENABLED_CERTEXT=$enableval ], + [ ENABLED_CERTEXT=no ] + ) + +if test "$ENABLED_CERTEXT" = "yes" +then + if test "$ENABLED_CERTEXT" = "no" + then + AC_MSG_ERROR([cannot enable certext without enabling certgen.]) + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" +fi + + # SEP AC_ARG_ENABLE([sep], [ --enable-sep Enable sep extensions (default: disabled)], @@ -1651,6 +1668,11 @@ then ENABLED_CERTREQ="yes" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_REQ" fi + if test "x$ENABLED_CERTEXT" = "xno" + then + ENABLED_CERTEXT="yes" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_EXT" + fi if test "x$ENABLED_PKCS7" = "xno" then ENABLED_PKCS7="yes" @@ -2374,6 +2396,7 @@ echo " * BLAKE2: $ENABLED_BLAKE2" echo " * keygen: $ENABLED_KEYGEN" echo " * certgen: $ENABLED_CERTGEN" echo " * certreq: $ENABLED_CERTREQ" +echo " * certext: $ENABLED_CERTEXT" echo " * HC-128: $ENABLED_HC128" echo " * RABBIT: $ENABLED_RABBIT" echo " * CHACHA: $ENABLED_CHACHA" diff --git a/gencertbuf.pl b/gencertbuf.pl index d3d116695..d58cd5aa7 100755 --- a/gencertbuf.pl +++ b/gencertbuf.pl @@ -20,6 +20,7 @@ my $outputFile = "./wolfssl/certs_test.h"; my @fileList_1024 = ( [ "./certs/1024/client-key.der", "client_key_der_1024" ], + [ "./certs/1024/client-keyPub.der", "client_keypub_der_1024" ], [ "./certs/1024/client-cert.der", "client_cert_der_1024" ], [ "./certs/1024/dh1024.der", "dh_key_der_1024" ], [ "./certs/1024/dsa1024.der", "dsa_key_der_1024" ], @@ -31,6 +32,7 @@ my @fileList_1024 = ( my @fileList_2048 = ( [ "./certs/client-key.der", "client_key_der_2048" ], + [ "./certs/client-keyPub.der", "client_keypub_der_2048" ], [ "./certs/client-cert.der", "client_cert_der_2048" ], [ "./certs/dh2048.der", "dh_key_der_2048" ], [ "./certs/dsa2048.der", "dsa_key_der_2048" ], @@ -140,6 +142,6 @@ sub file_to_hex { print OUT_FILE "\n"; - close($fp); + close($fp); } diff --git a/src/ssl.c b/src/ssl.c index aba00ac0c..aef24ee92 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1698,7 +1698,6 @@ int wolfSSL_KeyPemToDer(const unsigned char* pem, int pemSz, return ret; } - #endif /* !NO_CERTS */ @@ -2401,14 +2400,15 @@ int PemToDer(const unsigned char* buff, long longSz, int type, switch (type) { case CA_TYPE: /* same as below */ - case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; - case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; - case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; - case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; - case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; - case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; - case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; - default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; + case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; + case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; + case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; + case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; + case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; + case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; + case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; + case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; break; + default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; } switch (type) { @@ -3998,6 +3998,108 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) #endif /* WOLFSSL_CERT_GEN */ +#ifdef WOLFSSL_CERT_EXT +/* load pem public key from file into der buffer, return der size or error */ +int wolfSSL_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 = XFOPEN(fileName, "rb"); + buffer converted; + + WOLFSSL_ENTER("wolfSSL_PemPubKeyToDer"); + + if (file == XBADFILE) + ret = SSL_BAD_FILE; + else { + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); + + if (sz < 0) { + ret = SSL_BAD_FILE; + } + else if (sz > (long)sizeof(staticBuffer)) { + fileBuf = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_FILE); + if (fileBuf == NULL) + ret = MEMORY_E; + else + dynamic = 1; + } + + converted.buffer = 0; + + if (ret == 0) { + if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) + ret = SSL_BAD_FILE; + else + ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted, + 0, NULL, NULL); + + if (ret == 0) { + if (converted.length < (word32)derSz) { + XMEMCPY(derBuf, converted.buffer, converted.length); + ret = converted.length; + } + else + ret = BUFFER_E; + } + + XFREE(converted.buffer, 0, DYNAMIC_TYPE_CA); + } + + XFCLOSE(file); + if (dynamic) + XFREE(fileBuf, 0, DYNAMIC_TYPE_FILE); + } + + return ret; +} + +/* Return bytes written to buff or < 0 for error */ +int wolfSSL_PubKeyPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz) +{ + int ret; + buffer der; + + WOLFSSL_ENTER("wolfSSL_PubKeyPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + WOLFSSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + + der.buffer = NULL; + + ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL); + if (ret < 0) { + 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; + } + } + + XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY); + return ret; +} + +#endif /* WOLFSSL_CERT_EXT */ int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file, int format) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9ddd027fe..fabd3849e 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -120,9 +120,9 @@ #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) #elif defined(USER_TIME) - /* user time, and gmtime compatible functions, there is a gmtime + /* user time, and gmtime compatible functions, there is a gmtime implementation here that WINCE uses, so really just need some ticks - since the EPOCH + since the EPOCH */ struct tm { @@ -426,7 +426,7 @@ CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format, { CPU_BOOLEAN rtn_code; CPU_INT32S i; - CPU_INT32S val; + CPU_INT32S val; CPU_INT16U year; CPU_INT08U month; CPU_INT16U day; @@ -446,33 +446,33 @@ CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format, else { /* format == GENERALIZED_TIME */ year += btoi(date[i++]) * 1000; year += btoi(date[i++]) * 100; - } + } val = year; GetTime(&val, date, &i); year = (CPU_INT16U)val; val = 0; - GetTime(&val, date, &i); - month = (CPU_INT08U)val; + GetTime(&val, date, &i); + month = (CPU_INT08U)val; val = 0; - GetTime(&val, date, &i); + GetTime(&val, date, &i); day = (CPU_INT16U)val; val = 0; - GetTime(&val, date, &i); + GetTime(&val, date, &i); hour = (CPU_INT08U)val; val = 0; - GetTime(&val, date, &i); + GetTime(&val, date, &i); min = (CPU_INT08U)val; val = 0; - GetTime(&val, date, &i); + GetTime(&val, date, &i); sec = (CPU_INT08U)val; - return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType); + return NetSecure_ValidateDate(year, month, day, hour, min, sec, dateType); } #endif /* MICRIUM */ @@ -509,7 +509,7 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } b = input[i++]; - if (b >= ASN_LONG_LENGTH) { + if (b >= ASN_LONG_LENGTH) { word32 bytes = b & 0x7F; if ( (i+bytes) > maxIdx) { /* for reading bytes */ @@ -524,7 +524,7 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } else length = b; - + if ( (i+length) > maxIdx) { /* for user of length */ WOLFSSL_MSG("GetLength value exceeds buffer length"); return BUFFER_E; @@ -676,20 +676,20 @@ static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, word32 i = *inOutIdx; byte b; *oid = 0; - + b = input[i++]; - if (b != ASN_OBJECT_ID) + if (b != ASN_OBJECT_ID) return ASN_OBJECT_ID_E; - + if (GetLength(input, &i, &length, maxIdx) < 0) return ASN_PARSE_E; - + while(length--) *oid += input[i++]; /* just sum it up for now */ - + *inOutIdx = i; - + return 0; } @@ -701,29 +701,29 @@ WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, word32 i = *inOutIdx; byte b; *oid = 0; - + WOLFSSL_ENTER("GetAlgoId"); if (GetSequence(input, &i, &length, maxIdx) < 0) return ASN_PARSE_E; - + b = input[i++]; - if (b != ASN_OBJECT_ID) + if (b != ASN_OBJECT_ID) return ASN_OBJECT_ID_E; - + if (GetLength(input, &i, &length, maxIdx) < 0) return ASN_PARSE_E; - + while(length--) { /* odd HC08 compiler behavior here when input[i++] */ *oid += input[i]; i++; } /* 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) @@ -732,9 +732,9 @@ WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, else /* go back, didn't have it */ i--; - + *inOutIdx = i; - + return 0; } @@ -1002,7 +1002,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return UNICODE_SIZE_E; + return UNICODE_SIZE_E; } for (i = 0; i < passwordSz; i++) { @@ -1094,7 +1094,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ALGO_ID_E; + return ALGO_ID_E; } #ifdef WOLFSSL_SMALL_STACK @@ -1119,13 +1119,13 @@ 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; if (GetAlgoId(input, &inOutIdx, &oid, sz) < 0) return ASN_PARSE_E; - + first = input[inOutIdx - 2]; /* PKCS version alwyas 2nd to last byte */ second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ @@ -1149,13 +1149,13 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) 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) return ASN_PARSE_E; - + #ifdef WOLFSSL_SMALL_STACK salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (salt == NULL) @@ -1205,7 +1205,7 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) #endif return ASN_PARSE_E; } - + if (GetLength(input, &inOutIdx, &length, sz) < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -1273,41 +1273,41 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, /* 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) + if (b != ASN_OBJECT_ID) return ASN_OBJECT_ID_E; - + if (GetLength(input, inOutIdx, &length, 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) + if (b != 0) return ASN_EXPECT_0_E; } else /* go back, didn't have it */ (*inOutIdx)--; - + /* 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) return ASN_PARSE_E; - + /* could have 0 */ b = input[(*inOutIdx)++]; if (b != 0) (*inOutIdx)--; - + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; } /* end if */ @@ -1495,7 +1495,6 @@ 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, lbit; - int err; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -1532,6 +1531,8 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ if (sizes[i] <= MAX_SEQ_SZ) { + int err; + /* leading zero */ if (lbit) tmps[i][sizes[i]-1] = 0x00; @@ -1694,6 +1695,10 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) cert->extCertPolicyCrit = 0; #endif /* OPENSSL_EXTRA */ #endif /* WOLFSSL_SEP */ +#ifdef WOLFSSL_CERT_EXT + XMEMSET(cert->extCertPolicies, 0, MAX_CERTPOL_NB*MAX_CERTPOL_SZ); + cert->extCertPoliciesNb = 0; +#endif } @@ -1818,7 +1823,7 @@ static int StoreRsaKey(DecodedCert* cert) if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) return ASN_PARSE_E; - + recvd = cert->srcIdx - recvd; length += recvd; @@ -1881,7 +1886,7 @@ static int GetKey(DecodedCert* cert) 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) return ASN_PARSE_E; @@ -1898,7 +1903,7 @@ static int GetKey(DecodedCert* cert) b = cert->source[cert->srcIdx++]; if (b != 0x00) return ASN_EXPECT_0_E; - + return StoreRsaKey(cert); } @@ -1972,8 +1977,8 @@ static int GetKey(DecodedCert* cert) { int oidSz = 0; byte b = cert->source[cert->srcIdx++]; - - if (b != ASN_OBJECT_ID) + + if (b != ASN_OBJECT_ID) return ASN_OBJECT_ID_E; if (GetLength(cert->source,&cert->srcIdx,&oidSz,cert->maxIdx) < 0) @@ -2099,7 +2104,7 @@ static int GetName(DecodedCert* cert, int nameType) return ASN_PARSE_E; b = cert->source[cert->srcIdx++]; - if (b != ASN_OBJECT_ID) + if (b != ASN_OBJECT_ID) return ASN_OBJECT_ID_E; if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0) @@ -2114,7 +2119,7 @@ static int GetName(DecodedCert* cert, int nameType) int strLen; cert->srcIdx += 2; - id = cert->source[cert->srcIdx++]; + id = cert->source[cert->srcIdx++]; b = cert->source[cert->srcIdx++]; /* encoding */ if (GetLength(cert->source, &cert->srcIdx, &strLen, @@ -2505,7 +2510,7 @@ static int DateGreaterThan(const struct tm* a, const struct tm* b) 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; @@ -2646,10 +2651,10 @@ static int GetValidity(DecodedCert* cert, int verify) if (GetDate(cert, BEFORE) < 0 && verify) badDate = ASN_BEFORE_DATE_E; /* continue parsing */ - + if (GetDate(cert, AFTER) < 0 && verify) return ASN_AFTER_DATE_E; - + if (badDate != 0) return badDate; @@ -2728,7 +2733,7 @@ static word32 SetDigest(const byte* digest, word32 digSz, byte* output) XMEMCPY(&output[2], digest, digSz); return digSz + 2; -} +} static word32 BytePrecision(word32 value) @@ -2750,7 +2755,7 @@ WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output) output[i++] = (byte)length; else { output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); - + for (j = BytePrecision(length); j; --j) { output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE)); i++; @@ -2895,7 +2900,7 @@ static int SetCurve(ecc_key* key, byte* output) WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) { /* adding TAG_NULL and 0 to end */ - + /* hashTypes */ static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00 }; @@ -2928,9 +2933,9 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) static const byte sha512wRSA_AlgoID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00}; #endif /* NO_RSA */ - + /* ECDSA sigTypes */ - #ifdef HAVE_ECC + #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, @@ -2940,14 +2945,14 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) 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 */ - #ifdef HAVE_ECC + #ifdef HAVE_ECC /* ECC keyType */ /* no tags, so set tagSz smaller later */ static const byte ECC_AlgoID[] = { 0x2a, 0x86, 0x48, 0xCE, 0x3d, @@ -3043,7 +3048,7 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) algoName = sha512wRSA_AlgoID; break; #endif /* NO_RSA */ - #ifdef HAVE_ECC + #ifdef HAVE_ECC case CTC_SHAwECDSA: algoSz = sizeof(shawECDSA_AlgoID); algoName = shawECDSA_AlgoID; @@ -3077,7 +3082,7 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) algoName = RSA_AlgoID; break; #endif /* NO_RSA */ - #ifdef HAVE_ECC + #ifdef HAVE_ECC case ECDSAk: algoSz = sizeof(ECC_AlgoID); algoName = ECC_AlgoID; @@ -3095,7 +3100,7 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) } idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */ - seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray); + seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray); /* +1 for object id, curveID of curveSz follows for ecc */ seqArray[seqSz++] = ASN_OBJECT_ID; @@ -3207,16 +3212,16 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, case CTC_SHAwRSA: case CTC_SHAwDSA: case CTC_SHAwECDSA: - if (wc_ShaHash(buf, bufSz, digest) == 0) { + if (wc_ShaHash(buf, bufSz, digest) == 0) { typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + digestSz = SHA_DIGEST_SIZE; } break; #endif #ifndef NO_SHA256 case CTC_SHA256wRSA: case CTC_SHA256wECDSA: - if (wc_Sha256Hash(buf, bufSz, digest) == 0) { + if (wc_Sha256Hash(buf, bufSz, digest) == 0) { typeH = SHA256h; digestSz = SHA256_DIGEST_SIZE; } @@ -3225,7 +3230,7 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, #ifdef WOLFSSL_SHA512 case CTC_SHA512wRSA: case CTC_SHA512wECDSA: - if (wc_Sha512Hash(buf, bufSz, digest) == 0) { + if (wc_Sha512Hash(buf, bufSz, digest) == 0) { typeH = SHA512h; digestSz = SHA512_DIGEST_SIZE; } @@ -3234,16 +3239,16 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, #ifdef WOLFSSL_SHA384 case CTC_SHA384wRSA: case CTC_SHA384wECDSA: - if (wc_Sha384Hash(buf, bufSz, digest) == 0) { + if (wc_Sha384Hash(buf, bufSz, digest) == 0) { typeH = SHA384h; digestSz = SHA384_DIGEST_SIZE; - } + } break; #endif default: WOLFSSL_MSG("Verify Signautre has unsupported type"); } - + if (typeH == 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3275,17 +3280,17 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, 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 */ } #endif @@ -3383,7 +3388,7 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, if (wc_ecc_import_x963(key, keySz, pubKey) < 0) { WOLFSSL_MSG("ASN Key import error ECC"); } - else { + else { if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify, pubKey) != 0) { WOLFSSL_MSG("ECC verify hash error"); @@ -3405,7 +3410,7 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, default: WOLFSSL_MSG("Verify Key type unknown"); } - + #ifdef WOLFSSL_SMALL_STACK XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -3469,7 +3474,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--; @@ -3860,7 +3865,7 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) if (GetLength(input, &idx, &length, sz) < 0) return ASN_PARSE_E; - if (input[idx] == + if (input[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME)) { idx++; @@ -4044,7 +4049,6 @@ static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length; - byte unusedBits; WOLFSSL_ENTER("DecodeKeyUsage"); if (input[idx++] != ASN_BIT_STRING) { @@ -4057,15 +4061,12 @@ static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - unusedBits = input[idx++]; - length--; + /* pass the unusedBits value */ + idx++; length--; - 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; } @@ -4212,17 +4213,69 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) } #endif /* IGNORE_NAME_CONSTRAINTS */ +#ifdef WOLFSSL_CERT_EXT +/* Decode ITU-T X.690 OID format to a string representation + * return string length */ +static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) +{ + word32 val, idx = 0, nb_bytes; + size_t w_bytes = 0; -#ifdef WOLFSSL_SEP + if (out == NULL || in == NULL || outSz < 4 || inSz < 2) + return BAD_FUNC_ARG; + + /* first two byte must be interpreted as : 40 * int1 + int2 */ + val = (word16)in[idx++]; + + XSNPRINTF(out, outSz, "%d.%d", val / 40, val % 40); + w_bytes += XSTRLEN(out); + + while (idx < inSz) { + /* init value */ + val = 0; + nb_bytes = 0; + + /* check that output size is ok */ + if (w_bytes > (outSz - 3)) + return BUFFER_E; + + /* first bit is used to set if value is coded on 1 or multiple bytes */ + while ((in[idx+nb_bytes] & 0x80)) + nb_bytes++; + + if (!nb_bytes) + val = (word32)(in[idx++] & 0x7f); + else { + word32 base = 1, tmp = nb_bytes; + + while (tmp != 0) { + val += (word32)(in[idx+tmp] & 0x7f) * base; + base *= 128; + tmp--; + } + val += (word32)(in[idx++] & 0x7f) * base; + + idx += nb_bytes; + } + + XSNPRINTF(out+XSTRLEN(out), outSz, ".%d", val); + w_bytes = XSTRLEN(out); + } + + return 0; +} +#endif /* WOLFSSL_CERT_EXT */ + +#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; - int length = 0; + int total_length = 0, length = 0; WOLFSSL_ENTER("DecodeCertPolicy"); /* Unwrap certificatePolicies */ - if (GetSequence(input, &idx, &length, sz) < 0) { + if (GetSequence(input, &idx, &total_length, sz) < 0) { WOLFSSL_MSG("\tdeviceType isn't OID"); return ASN_PARSE_E; } @@ -4231,11 +4284,13 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) WOLFSSL_MSG("\tdeviceType isn't OID"); return ASN_PARSE_E; } + total_length -= (length+1); if (input[idx++] != ASN_OBJECT_ID) { WOLFSSL_MSG("\tdeviceType isn't OID"); return ASN_PARSE_E; } + total_length--; if (GetLength(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tCouldn't read length of deviceType"); @@ -4243,6 +4298,7 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) } if (length > 0) { +#if defined(WOLFSSL_SEP) cert->deviceType = (byte*)XMALLOC(length, cert->heap, 0); if (cert->deviceType == NULL) { WOLFSSL_MSG("\tCouldn't alloc memory for deviceType"); @@ -4250,6 +4306,46 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) } cert->deviceTypeSz = length; XMEMCPY(cert->deviceType, input + idx, length); +#elif defined(WOLFSSL_CERT_EXT) + /* decode cert policy */ + if (DecodePolicyOID(cert->extCertPolicies[0], MAX_CERTPOL_SZ, + input+idx, length) != 0) { + WOLFSSL_MSG("\tCouldn't read Policy OID 1"); + return ASN_PARSE_E; + } + cert->extCertPoliciesNb++; + + /* check if we have a second value */ + if (total_length) { + idx += length; + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tdeviceType isn't OID"); + return ASN_PARSE_E; + } + + if (input[idx++] != ASN_OBJECT_ID) { + WOLFSSL_MSG("\tdeviceType isn't OID"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tCouldn't read length of deviceType"); + return ASN_PARSE_E; + } + + /* decode cert policy */ + if (DecodePolicyOID(cert->extCertPolicies[1], MAX_CERTPOL_SZ, + input+idx, length) != 0) { + WOLFSSL_MSG("\tCouldn't read Policy OID 2"); + return ASN_PARSE_E; + } + cert->extCertPoliciesNb++; + } +#else + WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0); + return 0; +#endif } WOLFSSL_LEAVE("DecodeCertPolicy", 0); @@ -4277,15 +4373,21 @@ static int DecodeCertExtensions(DecodedCert* cert) if (input == NULL || sz == 0) return BAD_FUNC_ARG; - if (input[idx++] != ASN_EXTENSIONS) + if (input[idx++] != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); return ASN_PARSE_E; + } - if (GetLength(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) + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); return ASN_PARSE_E; - + } + while (idx < (word32)sz) { if (GetSequence(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); @@ -4376,8 +4478,10 @@ static int DecodeCertExtensions(DecodedCert* cert) cert->extCertPolicySet = 1; cert->extCertPolicyCrit = critical; #endif - if (DecodeCertPolicy(&input[idx], length, cert) < 0) - return ASN_PARSE_E; + #endif + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) + if (DecodeCertPolicy(&input[idx], length, cert) < 0) + return ASN_PARSE_E; #endif break; @@ -4474,7 +4578,7 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash); #endif #ifdef __cplusplus - } + } #endif @@ -4553,7 +4657,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) 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 */ @@ -4721,6 +4825,8 @@ const char* BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----"; const char* END_EC_PRIV = "-----END EC PRIVATE KEY-----"; const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; +const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; +const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; #if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) @@ -4880,22 +4986,20 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, #if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) /* Write a public RSA key to output */ -static int SetRsaPublicKey(byte* output, RsaKey* key, int outLen) +static int SetRsaPublicKey(byte* output, RsaKey* key, + int outLen, int with_header) { #ifdef WOLFSSL_SMALL_STACK byte* n = NULL; byte* e = NULL; - byte* algo = NULL; #else byte n[MAX_RSA_INT_SZ]; byte e[MAX_RSA_E_SZ]; - byte algo[MAX_ALGO_SZ]; #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; @@ -4976,45 +5080,65 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, int outLen) return BUFFER_E; } -#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; - } -#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 */ - - - /* write */ - idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); - /* 1 is for ASN_BIT_STRING */ /* check output size */ - if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { - #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 ( (seqSz + nSz + eSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif return BUFFER_E; } - /* algo */ - XMEMCPY(output + idx, algo, algoSz); - idx += algoSz; - /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; + /* headers */ + if (with_header) { + int algoSz; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + + 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; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(RSAk, algo, keyType, 0); + lenSz = SetLength(seqSz + nSz + eSz + 1, len); + len[lenSz++] = 0; /* trailing 0 */ + + /* write, 1 is for ASN_BIT_STRING */ + idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + + /* check output size */ + if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + #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 + + return BUFFER_E; + } + + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + output[idx++] = ASN_BIT_STRING; + /* length */ + XMEMCPY(output + idx, len, lenSz); + idx += lenSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + else + idx = 0; + /* seq */ XMEMCPY(output + idx, seq, seqSz); idx += seqSz; @@ -5028,7 +5152,6 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, int outLen) #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 return idx; @@ -5070,7 +5193,7 @@ static INLINE void FreeTmpRsas(byte** tmps, void* heap) (void)heap; - for (i = 0; i < RSA_INTS; i++) + for (i = 0; i < RSA_INTS; i++) XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA); } @@ -5174,7 +5297,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) written */ int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) { - return SetRsaPublicKey(output, key, inLen); + return SetRsaPublicKey(output, key, inLen, 1); } #endif /* WOLFSSL_KEY_GEN && !NO_RSA */ @@ -5215,6 +5338,15 @@ void wc_InitCert(Cert* cert) cert->altNamesSz = 0; cert->beforeDateSz = 0; cert->afterDateSz = 0; +#endif +#ifdef WOLFSSL_CERT_EXT + cert->skidSz = 0; + cert->akidSz = 0; + cert->keyUsage = 0; + cert->certPoliciesNb = 0; + XMEMSET(cert->akid, 0, CTC_MAX_AKID_SIZE); + XMEMSET(cert->skid, 0, CTC_MAX_SKID_SIZE); + XMEMSET(cert->certPolicies, 0, CTC_MAX_CERTPOL_NB*CTC_MAX_CERTPOL_SZ); #endif cert->keyType = RSA_KEY; XMEMSET(cert->serial, 0, CTC_SERIAL_SIZE); @@ -5268,9 +5400,18 @@ typedef struct DerCert { 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 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 */ @@ -5281,6 +5422,15 @@ typedef struct DerCert { 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 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 @@ -5314,11 +5464,11 @@ static int SetSerial(const byte* serial, byte* output) } -#ifdef HAVE_ECC +#ifdef HAVE_ECC /* 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 */ int algoSz; @@ -5350,58 +5500,63 @@ static int SetEccPublicKey(byte* output, ecc_key* key) return ret; } -#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; - } -#endif - /* headers */ - curveSz = SetCurve(key, curve); - if (curveSz <= 0) { + if (with_header) { #ifdef WOLFSSL_SMALL_STACK - XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + curve = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (curve == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } #endif - return curveSz; - } + 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); +#endif + 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, 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; + } #endif + algoSz = SetAlgoID(ECDSAk, algo, keyType, curveSz); - algoSz = SetAlgoID(ECDSAk, algo, keyType, curveSz); - lenSz = SetLength(pubSz + 1, len); - len[lenSz++] = 0; /* trailing 0 */ + lenSz = SetLength(pubSz + 1, len); + len[lenSz++] = 0; /* trailing 0 */ + + /* write, 1 is for ASN_BIT_STRING */ + idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output); + /* 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; + } + else + idx = 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); idx += pubSz; #ifdef WOLFSSL_SMALL_STACK - XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (with_header) { + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(curve, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -5412,8 +5567,6 @@ static int SetEccPublicKey(byte* output, ecc_key* key) #endif /* HAVE_ECC */ - - static INLINE byte itob(int number) { return (byte)number + 0x30; @@ -5444,7 +5597,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 */ } @@ -5660,29 +5813,51 @@ static byte GetNameId(int idx) } } +/* + 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* output, int *IdxInOut, + const byte* ext, int extSz) +{ + if (output == NULL || IdxInOut == NULL || ext == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(&output[*IdxInOut], ext, extSz); /* extensions */ + *IdxInOut += extSz; + + return *IdxInOut; +} + +/* encode extensions header, return total bytes written */ +static int SetExtensionsHeader(byte* output, 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 (output == 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; + seqSz = SetSequence(extSz, sequence); - return sz; + /* encode extensions length provided */ + lenSz = SetLength(extSz+seqSz, len); + + output[idx++] = ASN_EXTENSIONS; /* extensions id */ + XMEMCPY(&output[idx], len, lenSz); /* length */ + idx += lenSz; + + XMEMCPY(&output[idx], sequence, seqSz); /* sequence */ + idx += seqSz; + + return idx; } @@ -5691,13 +5866,298 @@ static int SetCa(byte* output) { static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff }; - + XMEMCPY(output, 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, const byte *oid, word32 oidSz, + byte *in, word32 inSz) +{ + int idx = 0; + + if (out == NULL || oid == NULL || in == NULL) + return BAD_FUNC_ARG; + + /* sequence, + 1 => byte to put value size */ + idx = SetSequence(inSz + oidSz + 1, out); + + 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, byte *input, word32 length) +{ + byte skid_len[MAX_LENGTH_SZ]; + byte skid_enc_len[MAX_LENGTH_SZ]; + int idx = 0, skid_lenSz, skid_enc_lenSz; + static const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 }; + + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + + /* length of value */ + skid_lenSz = SetLength(length, skid_len); + + /* length of encoded value */ + skid_enc_lenSz = SetLength(length + skid_lenSz + 1, skid_enc_len); + + /* sequence, + 1 => byte to put type size */ + idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz+1, + output); + + /* 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 type */ + output[idx++] = ASN_OCTET_STRING; + + /* put value len */ + 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, byte *input, word32 length) +{ + byte *enc_val; + int ret, enc_valSz; + static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04}; + static const byte akid_cs[] = { 0x80 }; + + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + + enc_val = (byte *)XMALLOC(length+3+sizeof(akid_cs), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (enc_val == NULL) + return MEMORY_E; + + /* sequence for ContentSpec & value */ + enc_valSz = SetOidValue(enc_val, akid_cs, sizeof(akid_cs), input, length); + if (enc_valSz == 0) { + XFREE(enc_val, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return 0; + } + + ret = SetOidValue(output, akid_oid, sizeof(akid_oid), enc_val, enc_valSz); + + XFREE(enc_val, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +/* encode Key Usage, return total bytes written + * RFC5280 : critical */ +static int SetKeyUsage(byte* output, word16 input) +{ + byte ku[5]; + int unusedBits = 0; + static const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04}; + + if (output == NULL) + return BAD_FUNC_ARG; + + /* Key Usage is a BitString */ + ku[0] = ASN_BIT_STRING; + + /* put the Bit String size */ + if (input > 255) { + ku[1] = (byte)3; + + /* compute unused bits */ + while (((((input >> 8) & 0xff) >> unusedBits) & 0x01) == 0) + unusedBits++; + } + else { + ku[1] = (byte)2; + + /* compute unused bits */ + while (((input >> unusedBits) & 0x01) == 0) + unusedBits++; + } + + /* put unused bits value */ + ku[2] = (byte)unusedBits; + + /* compute byte value */ + ku[3] = (byte)(input & 0xff); + if (input > 255) + ku[4] = (byte)((input >> 8) & 0xff); + + return SetOidValue(output, keyusage_oid, sizeof(keyusage_oid), + ku, (int)ku[1]+2); +} + +/* Encode OID string representation to ITU-T X.690 format */ +static int EncodePolicyOID(byte *out, word32 *outSz, const char *in) +{ + word32 val, idx = 0, nb_val; + char *token, *str; + word32 len; + + if (out == NULL || outSz == NULL || *outSz < 2 || in == NULL) + return BAD_FUNC_ARG; + + len = (word32)XSTRLEN(in); + + str = (char *)XMALLOC(len+1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XSTRNCPY(str, in, len); + str[len] = 0x00; + + nb_val = 0; + + /* parse value, and set corresponding Policy OID value */ + token = strtok(str, "."); + while (token != NULL) + { + val = (word32)atoi(token); + + if (nb_val == 0) { + if (val > 2) { + XFREE(str, NUL, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + out[idx] = (byte)(40 * val); + } + else if (nb_val == 1) { + if (val > 127) { + XFREE(str, NUL, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + if (idx > *outSz) { + XFREE(str, NUL, 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, NUL, 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 = strtok (NULL, "."); + nb_val++; + } + + *outSz = idx; + + XFREE(str, NUL, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} + +/* 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, + char input[MAX_CERTPOL_NB][MAX_CERTPOL_SZ], + word16 nb_certpol) +{ + 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; + + static const byte certpol_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04 }; + static 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); + memset(oid, 0, oidSz); + + ret = EncodePolicyOID(oid, &oidSz, input[i]); + if (ret != 0) + return ret; + + /* compute sequence value for the oid */ + ret = SetOidValue(der_oid[i], oid_oid, sizeof(oid_oid), oid, oidSz); + if (ret <= 0) + return ret; + else + der_oidSz[i] = (word32)ret; + } + + /* concatene 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, 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, byte *input, word32 length) +{ + /* Alternative Names come from certificate or computed by + * external function, so already encoded. Just copy value */ + XMEMCPY(output, input, length); + return length; +} +#endif /* WOLFSL_ALT_NAMES */ + + /* encode CertName into output, return total bytes written */ static int SetName(byte* output, CertName* name) { @@ -5744,7 +6204,7 @@ static int SetName(byte* output, CertName* name) else { thisLen++; /* str type */ thisLen++; /* id type */ - thisLen += JOINT_LEN; + thisLen += JOINT_LEN; firstSz = SetLength(JOINT_LEN + 1, firstLen); } thisLen += firstSz; @@ -5788,7 +6248,7 @@ static int SetName(byte* output, CertName* name) names[i].encoded[idx++] = 0x55; names[i].encoded[idx++] = 0x04; /* id type */ - names[i].encoded[idx++] = bType; + names[i].encoded[idx++] = bType; /* str type */ names[i].encoded[idx++] = GetNameType(name, i); } @@ -5865,7 +6325,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, if (rsaKey == NULL) return PUBLIC_KEY_E; der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, - sizeof(der->publicKey)); + sizeof(der->publicKey), 1); if (der->publicKeySz <= 0) return PUBLIC_KEY_E; } @@ -5874,7 +6334,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, if (cert->keyType == ECC_KEY) { if (eccKey == NULL) return PUBLIC_KEY_E; - der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey); + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); if (der->publicKeySz <= 0) return PUBLIC_KEY_E; } @@ -5929,34 +6389,152 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, 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) 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, + 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); +#ifdef WOLFSSL_CERT_EXT + /* SKID */ + if (cert->skidSz) { + /* check the provided SKID size */ + if (cert->skidSz > (int)sizeof(der->skid)) + return SKID_E; + + der->skidSz = SetSKID(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)sizeof(der->akid)) + return AKID_E; + + der->akidSz = SetAKID(der->akid, cert->akid, cert->akidSz); + 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, cert->keyUsage); + if (der->keyUsageSz == 0) + return KEYUSAGE_E; + + der->extensionsSz += der->keyUsageSz; + } + else + der->keyUsageSz = 0; + + /* Certificate Policies */ + if (cert->certPoliciesNb != 0) { + der->certPoliciesSz = SetCertificatePolicies(der->certPolicies, + cert->certPolicies, + cert->certPoliciesNb); + 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, + der->extensionsSz); if (der->extensionsSz == 0) return EXTENSIONS_E; - } + + /* put CA */ + if (der->caSz) { + ret = SetExtensions(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, &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, &der->extensionsSz, + der->skid, der->skidSz); + if (ret == 0) + return EXTENSIONS_E; + } + + /* put AKID */ + if (der->akidSz) { + ret = SetExtensions(der->extensions, &der->extensionsSz, + der->akid, der->akidSz); + if (ret == 0) + return EXTENSIONS_E; + } + + /* put KeyUsage */ + if (der->keyUsageSz) { + ret = SetExtensions(der->extensions, &der->extensionsSz, + der->keyUsage, der->keyUsageSz); + if (ret == 0) + return EXTENSIONS_E; + } + + /* put Certificate Policies */ + if (der->certPoliciesSz) { + ret = SetExtensions(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; @@ -6045,7 +6623,7 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, case CTC_SHAwECDSA: if ((ret = wc_ShaHash(buffer, sz, digest)) == 0) { typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + digestSz = SHA_DIGEST_SIZE; } break; #endif @@ -6071,19 +6649,19 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, WOLFSSL_MSG("MakeSignautre called with unsupported type"); ret = ALGO_ID_E; } - + if (ret != 0) 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 */ @@ -6091,7 +6669,7 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); } #endif - + #ifdef HAVE_ECC if (!rsaKey && eccKey) { word32 outSz = sigSz; @@ -6159,7 +6737,6 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, #endif ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz); - if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) ret = BUFFER_E; @@ -6289,7 +6866,7 @@ static int EncodeCertReq(Cert* cert, DerCert* der, if (rsaKey == NULL) return PUBLIC_KEY_E; der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, - sizeof(der->publicKey)); + sizeof(der->publicKey), 1); if (der->publicKeySz <= 0) return PUBLIC_KEY_E; } @@ -6298,30 +6875,98 @@ static int EncodeCertReq(Cert* cert, DerCert* der, if (cert->keyType == ECC_KEY) { if (eccKey == NULL) return PUBLIC_KEY_E; - der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey); + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); if (der->publicKeySz <= 0) return PUBLIC_KEY_E; } #endif /* HAVE_ECC */ + /* set the extensions */ + der->extensionsSz = 0; + /* CA */ if (cert->isCA) { der->caSz = SetCa(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)sizeof(der->skid)) + return SKID_E; + + der->skidSz = SetSKID(der->skid, cert->skid, cert->skidSz); + if (der->skidSz == 0) + return SKID_E; + + der->extensionsSz += der->skidSz; } else - der->extensionsSz = 0; + der->skidSz = 0; + + /* Key Usage */ + if (cert->keyUsage != 0){ + der->keyUsageSz = SetKeyUsage(der->keyUsage, cert->keyUsage); + if (der->keyUsageSz == 0) + return KEYUSAGE_E; + + der->extensionsSz += der->keyUsageSz; + } + else + der->keyUsageSz = 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, &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, &der->extensionsSz, + der->skid, der->skidSz); + if (ret == 0) + return EXTENSIONS_E; + } + + /* put AKID */ + if (der->akidSz) { + ret = SetExtensions(der->extensions, &der->extensionsSz, + der->akid, der->akidSz); + if (ret == 0) + return EXTENSIONS_E; + } + + /* put KeyUsage */ + if (der->keyUsageSz) { + ret = SetExtensions(der->extensions, &der->extensionsSz, + der->keyUsage, der->keyUsageSz); + if (ret == 0) + return EXTENSIONS_E; + } + +#endif /* WOLFSSL_CERT_EXT */ + } der->attribSz = SetReqAttrib(der->attrib, cert->challengePw, der->extensionsSz); @@ -6430,7 +7075,7 @@ int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, else sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType); } - + #ifdef WOLFSSL_SMALL_STACK XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -6442,8 +7087,9 @@ int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, WC_RNG* rng) { - int ret = wc_MakeCert(cert, buffer, buffSz, key, NULL, rng); + int ret; + ret = wc_MakeCert(cert, buffer, buffSz, key, NULL, rng); if (ret < 0) return ret; @@ -6452,7 +7098,330 @@ int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, } -#ifdef WOLFSSL_ALT_NAMES +#ifdef WOLFSSL_CERT_EXT + +/* Set KID from RSA or ECC public key */ +static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, + byte *ntruKey, word16 ntruKeySz, int kid_type) +{ + byte *buffer; + int bufferSz, ret; + +#ifndef HAVE_NTRU + (void)ntruKeySz; +#endif + + if (cert == NULL || (rsakey == NULL && eckey == NULL && ntruKey == NULL) || + (rsakey != NULL && eckey != NULL) || + (rsakey != NULL && ntruKey != NULL) || + (ntruKey != NULL && eckey != NULL) || + (kid_type != SKID_TYPE && kid_type != AKID_TYPE)) + return BAD_FUNC_ARG; + + buffer = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) + return MEMORY_E; + + /* RSA public key */ + if (rsakey != NULL) + bufferSz = SetRsaPublicKey(buffer, rsakey, MAX_PUBLIC_KEY_SZ, 0); +#ifdef HAVE_ECC + /* ECC public key */ + else if (eckey != NULL) + bufferSz = SetEccPublicKey(buffer, eckey, 0); +#endif /* HAVE_ECC */ +#ifdef HAVE_NTRU + /* NTRU public key */ + else if (ntruKey != NULL) { + bufferSz = MAX_PUBLIC_KEY_SZ; + ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( + ntruKeySz, ntruKey, (word16 *)(&bufferSz), buffer); + if (ret != NTRU_OK) + bufferSz = -1; + } +#endif + else + bufferSz = -1; + + if (bufferSz <= 0) { + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return PUBLIC_KEY_E; + } + + /* Compute SKID by hashing public key */ +#ifdef NO_SHA + if (kid_type == SKID_TYPE) { + ret = wc_Sha256Hash(buffer, bufferSz, cert->skid); + cert->skidSz = SHA256_DIGEST_SIZE; + } + else if (kid_type == AKID_TYPE) { + ret = wc_Sha256Hash(buffer, bufferSz, cert->akid); + cert->akidSz = SHA256_DIGEST_SIZE; + } + else + ret = BAD_FUNC_ARG; +#else /* NO_SHA */ + if (kid_type == SKID_TYPE) { + ret = wc_ShaHash(buffer, bufferSz, cert->skid); + cert->skidSz = SHA_DIGEST_SIZE; + } + else if (kid_type == AKID_TYPE) { + ret = wc_ShaHash(buffer, bufferSz, cert->akid); + cert->akidSz = SHA_DIGEST_SIZE; + } + else + ret = BAD_FUNC_ARG; +#endif /* NO_SHA */ + + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +/* 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, 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, SKID_TYPE); +} +#endif + +/* 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, AKID_TYPE); +} + + +/* 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, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem"); + return MEMORY_E; + } + + derSz = wolfSSL_PemPubKeyToDer(file, der, MAX_PUBLIC_KEY_SZ); + if (derSz <= 0) + { + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return derSz; + } + + /* Load PubKey in internal structure */ + rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (rsakey == NULL) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + if (wc_InitRsaKey(rsakey, NULL) != 0) { + WOLFSSL_MSG("wc_InitRsaKey failure"); + XFREE(rsakey, NULL, DYNAMIC_TYPE_RSA); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + idx = 0; + ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz); + if (ret != 0) { + WOLFSSL_MSG("wc_RsaPublicKeyDecode failed"); + wc_FreeRsaKey(rsakey); + XFREE(rsakey, NULL, DYNAMIC_TYPE_RSA); + rsakey = NULL; +#ifdef HAVE_ECC + /* Check to load ecc public key */ + eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (eckey == NULL) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + if (wc_ecc_init(eckey) != 0) { + WOLFSSL_MSG("wc_ecc_init failure"); + wc_ecc_free(eckey); + XFREE(eckey, NULL, DYNAMIC_TYPE_ECC); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + idx = 0; + ret = wc_EccPublicKeyDecode(der, &idx, eckey, derSz); + if (ret != 0) { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_ecc_free(eckey); + return PUBLIC_KEY_E; + } +#else + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return PUBLIC_KEY_E; +#endif /* HAVE_ECC */ + } + + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey); + + wc_FreeRsaKey(rsakey); + XFREE(rsakey, NULL, DYNAMIC_TYPE_RSA); +#ifdef HAVE_ECC + wc_ecc_free(eckey); + XFREE(eckey, NULL, DYNAMIC_TYPE_ECC); +#endif + return ret; +} + +/* Set AKID from certificate contains in buffer (DER encoded) */ +int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) +{ + int ret; + +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* decoded; +#else + DecodedCert decoded[1]; +#endif + + if (cert == NULL || der == NULL || derSz <= 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) + return MEMORY_E; +#endif + + /* decode certificate and get SKID that will be AKID of current cert */ + InitDecodedCert(decoded, (byte*)der, derSz, 0); + ret = ParseCert(decoded, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) { + FreeDecodedCert(decoded); + return ret; + } + + /* Subject Key Id not found !! */ + if (decoded->extSubjKeyIdSet == 0) { + FreeDecodedCert(decoded); + return ASN_NO_SKID; + } + + /* SKID invalid size */ + if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { + FreeDecodedCert(decoded); + return MEMORY_E; + } + + /* Put the SKID of CA to AKID of certificate */ + XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE); + cert->akidSz = KEYID_SIZE; + + FreeDecodedCert(decoded); + return 0; +} + +/* 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, NULL, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem"); + return MEMORY_E; + } + + derSz = wolfSSL_PemCertToDer(file, der, EIGHTK_BUF); + if (derSz <= 0) + { + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + return derSz; + } + + ret = wc_SetAuthKeyIdFromCert(cert, der, derSz); + XFREE(der, NULL, DYNAMIC_TYPE_CERT); + + return ret; +} + +/* Set KeyUsage from human readale string */ +int wc_SetKeyUsage(Cert *cert, const char *value) +{ + char *token, *str; + word32 len; + + if (cert == NULL || value == NULL) + return BAD_FUNC_ARG; + + cert->keyUsage = 0; + + str = (char *)XMALLOC(XSTRLEN(value)+1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XMEMSET(str, 0, XSTRLEN(value)+1); + XSTRNCPY(str, value, XSTRLEN(value)); + + /* parse value, and set corresponding Key Usage value */ + token = strtok(str, ","); + 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 + return KEYUSAGE_E; + + token = strtok(NULL, ","); + } + + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} +#endif /* WOLFSSL_CERT_EXT */ + + +#ifdef WOLFSSL_ALT_NAMES /* Set Alt Names from der cert, return 0 on success */ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) @@ -6473,7 +7442,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) if (decoded == NULL) return MEMORY_E; #endif - + InitDecodedCert(decoded, (byte*)der, derSz, 0); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); @@ -6487,7 +7456,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) decoded->srcIdx = decoded->extensionsIdx; b = decoded->source[decoded->srcIdx++]; - + if (b != ASN_EXTENSIONS) { ret = ASN_PARSE_E; } @@ -6562,7 +7531,7 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) WOLFSSL_ENTER("SetDatesFromCert"); if (derSz < 0) return derSz; - + #ifdef WOLFSSL_SMALL_STACK decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -6580,7 +7549,7 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) 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; @@ -6899,7 +7868,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, *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) @@ -6912,7 +7881,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, priv = (byte*)XMALLOC(ECC_MAXSIZE+1, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (priv == NULL) return MEMORY_E; - + pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (pub == NULL) { XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -6969,7 +7938,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, /* key header */ b = input[*inOutIdx]; *inOutIdx += 1; - + if (b != ASN_BIT_STRING) { ret = ASN_BITSTR_E; } @@ -7006,6 +7975,70 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, return ret; } +int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, + ecc_key* key, word32 inSz) +{ + int length; + int ret = 0; + + 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 defined(OPENSSL_EXTRA) + { + byte 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) + return ASN_PARSE_E; + + *inOutIdx += length; /* skip past */ + + /* ecc params information */ + b = input[(*inOutIdx)++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + *inOutIdx += length; /* skip past */ + + /* 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; + } + } + } /* openssl var block */ +#endif /* OPENSSL_EXTRA */ + + if (wc_ecc_import_x963(input+*inOutIdx, inSz - *inOutIdx, key) != 0) + return ASN_ECC_KEY_E; + + return ret; +} + #ifdef WOLFSSL_KEY_GEN @@ -7225,7 +8258,7 @@ static int DecodeSingleResponse(byte* source, resp->issuerKeyHash = source + idx; idx += length; - /* Read the serial number, it is handled as a string, not as a + /* 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) @@ -7274,10 +8307,10 @@ static int DecodeSingleResponse(byte* source, return ASN_PARSE_E; if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) return ASN_BEFORE_DATE_E; - + /* The following items are optional. Only check for them if there is more * unprocessed data in the singleResponse wrapper. */ - + if (((int)(idx - prevIndex) < wrapperSz) && (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))) { @@ -7318,7 +8351,7 @@ static int DecodeOcspRespExtensions(byte* source, if (GetLength(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) { @@ -7384,7 +8417,7 @@ static int DecodeResponseData(byte* source, * onto the next item. */ if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) - { + { idx += 2; /* Eat the value and length */ if (GetMyVersion(source, &idx, &version) < 0) return ASN_PARSE_E; @@ -7401,7 +8434,7 @@ static int DecodeResponseData(byte* source, } else return ASN_PARSE_E; - + /* save pointer to the producedAt time */ if (GetBasicDate(source, &idx, resp->producedDate, &resp->producedDateFormat, size) < 0) @@ -7462,7 +8495,7 @@ static int DecodeBasicOcspResponse(byte* source, if (DecodeResponseData(source, &idx, resp, size) < 0) return ASN_PARSE_E; - + /* Get the signature algorithm */ if (GetAlgoId(source, &idx, &resp->sigOID, size) < 0) return ASN_PARSE_E; @@ -7547,7 +8580,7 @@ int OcspResponseDecode(OcspResponse* resp) /* 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) return ASN_PARSE_E; @@ -7580,7 +8613,7 @@ int OcspResponseDecode(OcspResponse* resp) if (DecodeBasicOcspResponse(source, &idx, resp, size) < 0) return ASN_PARSE_E; - + return 0; } @@ -7596,7 +8629,7 @@ static word32 SetOcspReqExtensions(word32 extSz, byte* output, WOLFSSL_ENTER("SetOcspReqExtensions"); if (nonce == NULL || nonceSz == 0) return 0; - + seqArray[0][0] = ASN_OCTET_STRING; seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]); @@ -7759,7 +8792,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) WOLFSSL_MSG("\tnonceSz mismatch"); return cmp; } - + cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz); if (cmp != 0) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 7d9324952..3245c6428 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -208,7 +208,9 @@ int pbkdf2_test(void); int pkcs7enveloped_test(void); int pkcs7signed_test(void); #endif - +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) +int certext_test(void); +#endif /* General big buffer size for many tests. */ #define FOURK_BUF 4096 @@ -267,7 +269,6 @@ int wolfcrypt_test(void* args) #endif /* USE_FAST_MATH */ #endif /* !NO_BIG_INT */ - #ifndef NO_MD5 if ( (ret = md5_test()) != 0) return err_sys("MD5 test failed!\n", ret); @@ -486,6 +487,13 @@ int wolfcrypt_test(void* args) printf( "RSA test passed!\n"); #endif +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) + if ( (ret = certext_test()) != 0) + return err_sys("CERT EXT test failed!\n", ret); + else + printf( "CERT EXT test passed!\n"); +#endif + #ifndef NO_DH if ( (ret = dh_test()) != 0) return err_sys("DH test failed!\n", ret); @@ -3300,17 +3308,27 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #endif /* HAVE_NTRU */ + #ifndef NO_RSA #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) #ifdef FREESCALE_MQX static const char* clientKey = "a:\\certs\\client-key.der"; static const char* clientCert = "a:\\certs\\client-cert.der"; + #ifdef WOLFSSL_CERT_EXT + static const char* clientKeyPub = "a:\\certs\\client-keyPub.der"; + #endif #ifdef WOLFSSL_CERT_GEN static const char* caKeyFile = "a:\\certs\\ca-key.der"; + #ifdef WOLFSSL_CERT_EXT + static const char* caKeyPubFile = "a:\\certs\\ca-keyPub.der"; + #endif static const char* caCertFile = "a:\\certs\\ca-cert.pem"; #ifdef HAVE_ECC static const char* eccCaKeyFile = "a:\\certs\\ecc-key.der"; + #ifdef WOLFSSL_CERT_EXT + static const char* eccCaKeyPubFile = "a:\\certs\\ecc-keyPub.der"; + #endif static const char* eccCaCertFile = "a:\\certs\\server-ecc.pem"; #endif #endif @@ -3319,13 +3337,25 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) static char* clientCert = "certs/client-cert.der"; void set_clientKey(char *key) { clientKey = key ; } void set_clientCert(char *cert) { clientCert = cert ; } + #ifdef WOLFSSL_CERT_EXT + static const char* clientKeyPub = "certs/client-keyPub.der"; + void set_clientKeyPub(char *key) { clientKeyPub = key ; } + #endif #ifdef WOLFSSL_CERT_GEN static char* caKeyFile = "certs/ca-key.der"; + #ifdef WOLFSSL_CERT_EXT + static const char* caKeyPubFile = "certs/ca-keyPub.der"; + void set_caKeyPubFile (char * key) { caKeyPubFile = key ; } + #endif static char* caCertFile = "certs/ca-cert.pem"; void set_caKeyFile (char * key) { caKeyFile = key ; } void set_caCertFile(char * cert) { caCertFile = cert ; } #ifdef HAVE_ECC static const char* eccCaKeyFile = "certs/ecc-key.der"; + #ifdef WOLFSSL_CERT_EXT + static const char* eccCaKeyPubFile = "certs/ecc-keyPub.der"; + void set_eccCaKeyPubFile(char * key) { eccCaKeyPubFile = key ; } + #endif static const char* eccCaCertFile = "certs/server-ecc.pem"; void set_eccCaKeyFile (char * key) { eccCaKeyFile = key ; } void set_eccCaCertFile(char * cert) { eccCaCertFile = cert ; } @@ -3334,11 +3364,17 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #else static const char* clientKey = "./certs/client-key.der"; static const char* clientCert = "./certs/client-cert.der"; + #ifdef WOLFSSL_CERT_EXT + static const char* clientKeyPub = "./certs/client-keyPub.der"; + #endif #ifdef WOLFSSL_CERT_GEN static const char* caKeyFile = "./certs/ca-key.der"; static const char* caCertFile = "./certs/ca-cert.pem"; #ifdef HAVE_ECC static const char* eccCaKeyFile = "./certs/ecc-key.der"; + #ifdef WOLFSSL_CERT_EXT + static const char* eccCaKeyPubFile = "./certs/ecc-keyPub.der"; + #endif static const char* eccCaCertFile = "./certs/server-ecc.pem"; #endif #endif @@ -3346,11 +3382,202 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #endif +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) +int certext_test(void) +{ + DecodedCert cert; + byte* tmp; + size_t bytes; + FILE *file; + int ret; + + /* created from rsa_test : othercert.der */ + byte skid_rsa[] = "\x33\xD8\x45\x66\xD7\x68\x87\x18\x7E\x54" + "\x0D\x70\x27\x91\xC7\x26\xD7\x85\x65\xC0"; + + /* created from rsa_test : othercert.der */ + byte akid_rsa[] = "\x27\x8E\x67\x11\x74\xC3\x26\x1D\x3F\xED" + "\x33\x63\xB3\xA4\xD8\x1D\x30\xE5\xE8\xD5"; + +#ifdef HAVE_ECC + /* created from rsa_test : certecc.der */ + byte akid_ecc[] = "\x5D\x5D\x26\xEF\xAC\x7E\x36\xF9\x9B\x76" + "\x15\x2B\x4A\x25\x02\x23\xEF\xB2\x89\x30"; +#endif + + /* created from rsa_test : cert.der */ + byte kid_ca[] = "\x33\xD8\x45\x66\xD7\x68\x87\x18\x7E\x54" + "\x0D\x70\x27\x91\xC7\x26\xD7\x85\x65\xC0"; + + tmp = (byte*)malloc(FOURK_BUF); + if (tmp == NULL) + return -200; + + /* load othercert.pem (Cert signed by an authority) */ +#ifdef FREESCALE_MQX + file = fopen("a:\\certs\\othercert.der", "rb"); +#else + file = fopen("./othercert.der", "rb"); +#endif + if (!file) { + free(tmp); + return -200; + } + + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); + + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) + return -201; + + /* check the SKID from a RSA certificate */ + if (XMEMCMP(skid_rsa, cert.extSubjKeyId, cert.extSubjKeyIdSz)) + return -202; + + /* check the AKID from an RSA certificate */ + if (XMEMCMP(akid_rsa, cert.extAuthKeyId, cert.extAuthKeyIdSz)) + return -203; + + /* check the Key Usage from an RSA certificate */ + if (!cert.extKeyUsageSet) + return -204; + + if (cert.extKeyUsage != (KEYUSE_KEY_ENCIPHER|KEYUSE_KEY_AGREE)) + return -205; + + /* check the CA Basic Constraints from an RSA certificate */ + if (cert.isCA) + return -206; + + /* check the Certificate Policies Id */ + if (cert.extCertPoliciesNb != 1) + return -227; + + if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) + return -228; + + FreeDecodedCert(&cert); + +#ifdef HAVE_ECC + /* load certecc.pem (Cert signed by an authority) */ +#ifdef FREESCALE_MQX + file = fopen("a:\\certs\\certecc.der", "rb"); +#else + file = fopen("./certecc.der", "rb"); +#endif + if (!file) { + free(tmp); + return -210; + } + + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); + + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) + return -211; + + /* check the SKID from a ECC certificate */ + if (XMEMCMP(skid_rsa, cert.extSubjKeyId, cert.extSubjKeyIdSz)) + return -212; + + /* check the AKID from an ECC certificate */ + if (XMEMCMP(akid_ecc, cert.extAuthKeyId, cert.extAuthKeyIdSz)) + return -213; + + /* check the Key Usage from an ECC certificate */ + if (!cert.extKeyUsageSet) + return -214; + + if (cert.extKeyUsage != (KEYUSE_DIGITAL_SIG|KEYUSE_CONTENT_COMMIT)) + return -215; + + /* check the CA Basic Constraints from an ECC certificate */ + if (cert.isCA) + return -216; + + /* check the Certificate Policies Id */ + if (cert.extCertPoliciesNb != 2) + return -217; + + if (strncmp(cert.extCertPolicies[0], "2.4.589440.587.101.2.1.9632587.1", 32)) + return -218; + + if (strncmp(cert.extCertPolicies[1], "1.2.13025.489.1.113549", 22)) + return -219; + + FreeDecodedCert(&cert); +#endif /* HAVE_ECC */ + + /* load cert.pem (self signed certificate) */ +#ifdef FREESCALE_MQX + file = fopen("a:\\certs\\cert.der", "rb"); +#else + file = fopen("./cert.der", "rb"); +#endif + if (!file) { + free(tmp); + return -220; + } + + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); + + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); + if (ret != 0) + return -221; + + /* check the SKID from a CA certificate */ + if (XMEMCMP(kid_ca, cert.extSubjKeyId, cert.extSubjKeyIdSz)) + return -222; + + /* check the AKID from an CA certificate */ + if (XMEMCMP(kid_ca, cert.extAuthKeyId, cert.extAuthKeyIdSz)) + return -223; + + /* check the Key Usage from CA certificate */ + if (!cert.extKeyUsageSet) + return -224; + + if (cert.extKeyUsage != (KEYUSE_KEY_CERT_SIGN|KEYUSE_CRL_SIGN)) + return -225; + + /* check the CA Basic Constraints CA certificate */ + if (!cert.isCA) + return -226; + + /* check the Certificate Policies Id */ + if (cert.extCertPoliciesNb != 2) + return -227; + + if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) + return -228; + + if (strncmp(cert.extCertPolicies[1], "1.2.840.113549.1.9.16.6.5", 25)) + return -229; + + FreeDecodedCert(&cert); + + return 0; +} +#endif /* defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) */ + + int rsa_test(void) { byte* tmp; size_t bytes; RsaKey key; +#ifdef WOLFSSL_CERT_EXT + RsaKey keypub; +#endif WC_RNG rng; word32 idx = 0; int ret; @@ -3359,7 +3586,7 @@ int rsa_test(void) byte out[256]; byte plain[256]; #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - FILE* file, * file2; + FILE *file, *file2; #endif #ifdef WOLFSSL_TEST_CERT DecodedCert cert; @@ -3473,6 +3700,42 @@ int rsa_test(void) (void)bytes; #endif +#ifdef WOLFSSL_CERT_EXT + +#ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, client_keypub_der_1024, sizeof_client_keypub_der_1024); + bytes = sizeof_client_keypub_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, client_keypub_der_2048, sizeof_client_keypub_der_2048); + bytes = sizeof_client_keypub_der_2048; +#else + file = fopen(clientKeyPub, "rb"); + if (!file) { + err_sys("can't open ./certs/client-keyPub.der, " + "Please run from wolfSSL home dir", -40); + free(tmp); + return -50; + } + + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#endif /* USE_CERT_BUFFERS */ + + ret = wc_InitRsaKey(&keypub, 0); + if (ret != 0) { + free(tmp); + return -51; + } + idx = 0; + + ret = wc_RsaPublicKeyDecode(tmp, &idx, &keypub, (word32)bytes); + if (ret != 0) { + free(tmp); + wc_FreeRsaKey(&keypub); + return -52; + } +#endif /* WOLFSSL_CERT_EXT */ + #ifdef WOLFSSL_KEY_GEN { byte* der; @@ -3634,6 +3897,39 @@ int rsa_test(void) myCert.isCA = 1; myCert.sigType = CTC_SHA256wRSA; +#ifdef WOLFSSL_CERT_EXT + /* add Policies */ + strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", + CTC_MAX_CERTPOL_SZ); + strncpy(myCert.certPolicies[1], "1.2.840.113549.1.9.16.6.5", + CTC_MAX_CERTPOL_SZ); + myCert.certPoliciesNb = 2; + + /* add SKID from the Public Key */ + if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) { + free(pem); + free(derCert); + free(tmp); + return -398; + } + + /* add AKID from the Public Key */ + if (wc_SetAuthKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) { + free(pem); + free(derCert); + free(tmp); + return -399; + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&myCert,"cRLSign,keyCertSign") != 0) { + free(pem); + free(derCert); + free(tmp); + return -400; + } +#endif /* WOLFSSL_CERT_EXT */ + certSz = wc_MakeSelfCert(&myCert, derCert, FOURK_BUF, &key, &rng); if (certSz < 0) { free(derCert); @@ -3775,6 +4071,37 @@ int rsa_test(void) strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); +#ifdef WOLFSSL_CERT_EXT + /* add Policies */ + strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", + CTC_MAX_CERTPOL_SZ); + myCert.certPoliciesNb =1; + + /* add SKID from the Public Key */ + if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) { + free(pem); + free(derCert); + free(tmp); + return -398; + } + + /* add AKID from the CA certificate */ + if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) { + free(pem); + free(derCert); + free(tmp); + return -399; + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&myCert,"keyEncipherment,keyAgreement") != 0) { + free(pem); + free(derCert); + free(tmp); + return -400; + } +#endif /* WOLFSSL_CERT_EXT */ + ret = wc_SetIssuer(&myCert, caCertFile); if (ret < 0) { free(derCert); @@ -3803,7 +4130,6 @@ int rsa_test(void) return -408; } - #ifdef WOLFSSL_TEST_CERT InitDecodedCert(&decode, derCert, certSz, 0); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); @@ -3887,6 +4213,9 @@ int rsa_test(void) size_t bytes3; word32 idx3 = 0; FILE* file3; +#ifdef WOLFSSL_CERT_EXT + ecc_key caKeyPub; +#endif #ifdef WOLFSSL_TEST_CERT DecodedCert decode; #endif @@ -3935,6 +4264,72 @@ int rsa_test(void) strncpy(myCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); strncpy(myCert.subject.email, "info@wolfssl.com", CTC_NAME_SIZE); +#ifdef WOLFSSL_CERT_EXT + /* add Policies */ + strncpy(myCert.certPolicies[0], "2.4.589440.587.101.2.1.9632587.1", + CTC_MAX_CERTPOL_SZ); + strncpy(myCert.certPolicies[1], "1.2.13025.489.1.113549", + CTC_MAX_CERTPOL_SZ); + myCert.certPoliciesNb = 2; + + + file3 = fopen(eccCaKeyPubFile, "rb"); + if (!file3) { + free(derCert); + free(pem); + free(tmp); + return -5500; + } + + bytes3 = fread(tmp, 1, FOURK_BUF, file3); + fclose(file3); + + wc_ecc_init(&caKeyPub); + if (ret != 0) { + free(derCert); + free(pem); + free(tmp); + return -5501; + } + + idx3 = 0; + ret = wc_EccPublicKeyDecode(tmp, &idx3, &caKeyPub, (word32)bytes3); + if (ret != 0) { + free(derCert); + free(pem); + free(tmp); + wc_ecc_free(&caKeyPub); + return -5502; + } + + /* add SKID from the Public Key */ + if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) { + free(pem); + free(derCert); + free(tmp); + wc_ecc_free(&caKeyPub); + return -5503; + } + + /* add AKID from the Public Key */ + if (wc_SetAuthKeyIdFromPublicKey(&myCert, NULL, &caKeyPub) != 0) { + free(pem); + free(derCert); + free(tmp); + wc_ecc_free(&caKeyPub); + return -5504; + } + wc_ecc_free(&caKeyPub); + + /* add Key Usage */ + if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation") != 0) { + free(pem); + free(derCert); + free(tmp); + return -5505; + } +#endif /* WOLFSSL_CERT_EXT */ + ret = wc_SetIssuer(&myCert, eccCaCertFile); if (ret < 0) { free(pem); @@ -3944,7 +4339,7 @@ int rsa_test(void) return -5405; } - certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, NULL, &caKey, &rng); + certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng); if (certSz < 0) { free(pem); free(derCert); @@ -4144,6 +4539,35 @@ int rsa_test(void) strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); +#ifdef WOLFSSL_CERT_EXT + + /* add SKID from the Public Key */ + if (wc_SetSubjectKeyIdFromNtruPublicKey(&myCert, public_key, + public_key_len) != 0) { + free(pem); + free(derCert); + free(tmp); + return -496; + } + + /* add AKID from the CA certificate */ + if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) { + free(pem); + free(derCert); + free(tmp); + return -495; + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation," + "keyEncipherment,keyAgreement") != 0) { + free(pem); + free(derCert); + free(tmp); + return -494; + } +#endif /* WOLFSSL_CERT_EXT */ + ret = wc_SetIssuer(&myCert, caCertFile); if (ret < 0) { free(derCert); @@ -4279,6 +4703,25 @@ int rsa_test(void) strncpy(req.subject.email, "info@yassl.com", CTC_NAME_SIZE); req.sigType = CTC_SHA256wRSA; +#ifdef WOLFSSL_CERT_EXT + /* add SKID from the Public Key */ + if (wc_SetSubjectKeyIdFromPublicKey(&req, &keypub, NULL) != 0) { + free(pem); + free(der); + free(tmp); + return -496; + } + + /* add Key Usage */ + if (wc_SetKeyUsage(&req,"digitalSignature,nonRepudiation," + "keyEncipherment,keyAgreement") != 0) { + free(pem); + free(der); + free(tmp); + return -494; + } +#endif /* WOLFSSL_CERT_EXT */ + derSz = wc_MakeCertReq(&req, der, FOURK_BUF, &key, NULL); if (derSz < 0) { free(pem); @@ -4352,6 +4795,9 @@ int rsa_test(void) #endif /* WOLFSSL_CERT_GEN */ wc_FreeRsaKey(&key); +#ifdef WOLFSSL_CERT_EXT + wc_FreeRsaKey(&keypub); +#endif #ifdef HAVE_CAVIUM wc_RsaFreeCavium(&key); #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index da140a42a..d80c728e0 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1069,10 +1069,19 @@ WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version); WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version); WOLFSSL_API int wolfSSL_GetObjectSize(void); /* object size based on build */ WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version); -WOLFSSL_API int wolfSSL_KeyPemToDer(const unsigned char*, int sz, unsigned char*, - int, const char*); -WOLFSSL_API int wolfSSL_CertPemToDer(const unsigned char*, int sz, unsigned char*, - int, int); +WOLFSSL_API int wolfSSL_KeyPemToDer(const unsigned char*, int, + unsigned char*, int, const char*); +WOLFSSL_API int wolfSSL_CertPemToDer(const unsigned char*, int, + unsigned char*, int, int); +#ifdef WOLFSSL_CERT_EXT + #ifndef WOLFSSL_PEMPUBKEY_TODER_DEFINED + WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz); + WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int, + unsigned char*, int); + #define WOLFSSL_PEMPUBKEY_TODER_DEFINED + #endif +#endif /* WOLFSSL_CERT_EXT */ typedef void (*CallbackCACache)(unsigned char* der, int sz, int type); typedef void (*CbMissingCRL)(const char* url); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 311cad852..b39114fa4 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -172,12 +172,20 @@ enum Misc_ASN { MAX_ATTRIB_SZ = MAX_SEQ_SZ * 3 + (11 + MAX_SEQ_SZ) * 2 + MAX_PRSTR_SZ + CTC_NAME_SIZE, /* 11 is the OID size */ #endif - #ifdef WOLFSSL_ALT_NAMES + #if defined(WOLFSSL_ALT_NAMES) || defined(WOLFSSL_CERT_EXT) MAX_EXTENSIONS_SZ = 1 + MAX_LENGTH_SZ + CTC_MAX_ALT_SIZE, #else MAX_EXTENSIONS_SZ = 1 + MAX_LENGTH_SZ + MAX_CA_SZ, #endif /* Max total extensions, id + len + others */ +#endif +#ifdef WOLFSSL_CERT_EXT + MAX_KID_SZ = 45, /* Max encoded KID length (SHA-256 case) */ + MAX_KEYUSAGE_SZ = 18, /* Max encoded Key Usage length */ + MAX_OID_SZ = 32, /* Max DER length of OID*/ + MAX_OID_STRING_SZ = 64, /* Max string length representation of OID*/ + MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ + MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, #endif MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ MAX_OCSP_NONCE_SZ = 18, /* OCSP Nonce size */ @@ -277,17 +285,23 @@ enum VerifyType { VERIFY = 1 }; +#ifdef WOLFSSL_CERT_EXT +enum KeyIdType { + SKID_TYPE = 0, + AKID_TYPE = 1 +}; +#endif /* Key usage extension bits */ -#define KEYUSE_DIGITAL_SIG 0x0100 -#define KEYUSE_CONTENT_COMMIT 0x0080 -#define KEYUSE_KEY_ENCIPHER 0x0040 -#define KEYUSE_DATA_ENCIPHER 0x0020 -#define KEYUSE_KEY_AGREE 0x0010 -#define KEYUSE_KEY_CERT_SIGN 0x0008 -#define KEYUSE_CRL_SIGN 0x0004 -#define KEYUSE_ENCIPHER_ONLY 0x0002 -#define KEYUSE_DECIPHER_ONLY 0x0001 +#define KEYUSE_DIGITAL_SIG 0x0080 +#define KEYUSE_CONTENT_COMMIT 0x0040 +#define KEYUSE_KEY_ENCIPHER 0x0020 +#define KEYUSE_DATA_ENCIPHER 0x0010 +#define KEYUSE_KEY_AGREE 0x0008 +#define KEYUSE_KEY_CERT_SIGN 0x0004 +#define KEYUSE_CRL_SIGN 0x0002 +#define KEYUSE_ENCIPHER_ONLY 0x0001 +#define KEYUSE_DECIPHER_ONLY 0x8000 #define EXTKEYUSE_ANY 0x08 #define EXTKEYUSE_OCSP_SIGN 0x04 @@ -475,6 +489,10 @@ struct DecodedCert { byte extCertPolicyCrit; #endif /* OPENSSL_EXTRA */ #endif /* WOLFSSL_SEP */ +#ifdef WOLFSSL_CERT_EXT + char extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; + int extCertPoliciesNb; +#endif /* WOLFSSL_CERT_EXT */ }; extern const char* BEGIN_CERT; @@ -495,6 +513,8 @@ extern const char* BEGIN_EC_PRIV; extern const char* END_EC_PRIV; extern const char* BEGIN_DSA_PRIV; extern const char* END_DSA_PRIV; +extern const char* BEGIN_PUB_KEY; +extern const char* END_PUB_KEY; #ifdef NO_SHA #define SIGNER_DIGEST_SIZE SHA256_DIGEST_SIZE diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 7aea6f927..6a1ab73bd 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -47,7 +47,10 @@ enum CertType { CERTREQ_TYPE, DSA_TYPE, ECC_TYPE, - RSA_TYPE + RSA_TYPE, + PUBLICKEY_TYPE, + RSA_PUBLICKEY_TYPE, + ECC_PUBLICKEY_TYPE }; @@ -79,10 +82,18 @@ enum Ctc_Encoding { #endif enum Ctc_Misc { - CTC_NAME_SIZE = 64, - CTC_DATE_SIZE = 32, - CTC_MAX_ALT_SIZE = 16384, /* may be huge */ - CTC_SERIAL_SIZE = 8 + CTC_NAME_SIZE = 64, + CTC_DATE_SIZE = 32, + CTC_MAX_ALT_SIZE = 16384, /* may be huge */ + CTC_SERIAL_SIZE = 8, +#ifdef WOLFSSL_CERT_EXT + /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum + * We support only hash */ + CTC_MAX_SKID_SIZE = SHA256_DIGEST_SIZE, + CTC_MAX_AKID_SIZE = SHA256_DIGEST_SIZE, + CTC_MAX_CERTPOL_SZ = 64, + CTC_MAX_CERTPOL_NB = 2 /* Max number of Certificate Policy */ +#endif /* WOLFSSL_CERT_EXT */ }; typedef struct CertName { @@ -125,6 +136,15 @@ typedef struct Cert { byte afterDate[CTC_DATE_SIZE]; /* after date copy */ int afterDateSz; /* size of copy */ #endif +#ifdef WOLFSSL_CERT_EXT + byte skid[CTC_MAX_SKID_SIZE]; /* Subject Key Identifier */ + int skidSz; /* SKID size in bytes */ + byte akid[CTC_MAX_AKID_SIZE]; /* Authority Key Identifier */ + int akidSz; /* AKID size in bytes */ + word16 keyUsage; /* Key Usage */ + char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ]; + word16 certPoliciesNb; /* Number of Cert Policy */ +#endif #ifdef WOLFSSL_CERT_REQ char challengePw[CTC_NAME_SIZE]; #endif @@ -168,6 +188,49 @@ WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int); WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); +#ifdef WOLFSSL_CERT_EXT +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, + ecc_key *eckey); +WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz); +WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, + ecc_key *eckey); +WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file); + +#ifdef HAVE_NTRU +WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, + word16 ntruKeySz); +#endif + +/* Set the KeyUsage. + * Value is a string separated tokens with ','. Accepted tokens are : + * digitalSignature,nonRepudiation,contentCommitment,keyCertSign,cRLSign, + * dataEncipherment,keyAgreement,keyEncipherment,encipherOnly and decipherOnly. + * + * nonRepudiation and contentCommitment are for the same usage. + */ +WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); + +/* 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 */ +WOLFSSL_API int wc_SetCertificatePolicies(Cert *cert, const char **input); + +#ifndef WOLFSSL_PEMPUBKEY_TODER_DEFINED + #ifndef NO_FILESYSTEM + /* forward from wolfssl */ + WOLFSSL_API int wolfSSL_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif + + /* forward from wolfssl */ + WOLFSSL_API int wolfSSL_PubKeyPemToDer(const unsigned char*, int, + unsigned char*, int); + #define WOLFSSL_PEMPUBKEY_TODER_DEFINED +#endif /* WOLFSSL_PEMPUBKEY_TODER_DEFINED */ +#endif /* WOLFSSL_CERT_EXT */ + #ifdef HAVE_NTRU WOLFSSL_API int wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz, const byte* ntruKey, word16 keySz, @@ -186,9 +249,13 @@ WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); #ifdef HAVE_ECC /* private key helpers */ - WOLFSSL_API int wc_EccPrivateKeyDecode(const byte* input,word32* inOutIdx, - ecc_key*,word32); + WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*, + ecc_key*, word32); WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); + + /* public key helper */ + WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*, + ecc_key*, word32); #endif /* DER encode signature */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 6e783085c..f08ecbd98 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -153,6 +153,14 @@ enum { SRP_VERIFY_E = -218, /* SRP proof verification failed. */ SRP_BAD_KEY_E = -219, /* SRP bad ephemeral values. */ + ASN_NO_SKID = -220, /* ASN no Subject Key Identifier found */ + ASN_NO_AKID = -221, /* ASN no Authority Key Identifier found */ + ASN_NO_KEYUSAGE = -223, /* ASN no Key Usage found */ + SKID_E = -224, /* setting Subject Key Identifier error */ + AKID_E = -225, /* setting Authority Key Identifier error */ + KEYUSAGE_E = -226, /* Bad Key Usage value */ + CERTPOLICIES_E = -227, /* setting Certificate Policies error */ + MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h index 2e604080d..ad519f76d 100644 --- a/wolfssl/wolfcrypt/logging.h +++ b/wolfssl/wolfcrypt/logging.h @@ -25,6 +25,10 @@ #ifndef WOLFSSL_LOGGING_H #define WOLFSSL_LOGGING_H +#ifdef DEBUG_WOLFSSL +#include +#endif + #include #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 3aa6a8d03..488627ede 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -519,7 +519,11 @@ static char *fgets(char *buff, int sz, FILE *fp) #include "mqx.h" #ifndef NO_FILESYSTEM #include "mfs.h" - #include "fio.h" + #if MQX_USE_IO_OLD + #include "fio.h" + #else + #include "nio.h" + #endif #endif #ifndef SINGLE_THREADED #include "mutex.h" diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 324c8d1b1..dada779b5 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -191,6 +191,7 @@ #ifndef STRING_USER #include + #include /* for snprintf */ char* mystrnstr(const char* s1, const char* s2, unsigned int n); #define XMEMCPY(d,s,l) memcpy((d),(s),(l))