diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index cc51ad2a1..84f9da44a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4861,6 +4861,92 @@ int GetTimeString(byte* date, int format, char* buf, int len) #endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) + +/* set current time string, either UTC or GeneralizedTime */ +int GetAsnTimeString(byte* buf, word32 len) +{ + time_t currTime; + struct tm* ts = NULL; + struct tm* tmpTime = NULL; +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + byte* data_ptr = buf; + word32 data_len = 0; + int year, mon, day, hour, min, sec; + + WOLFSSL_ENTER("SetAsnTimeString"); + + if (buf == NULL || len == 0) + return BAD_FUNC_ARG; + + currTime = XTIME(0); + ts = (struct tm *)XGMTIME(&currTime, tmpTime); + if (ts == NULL){ + WOLFSSL_MSG("failed to get time data."); + return ASN_TIME_E; + } + + /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for + * the null terminator. ASN encoded values leave off the terminator. */ + + if (ts->tm_year >= 50 && ts->tm_year < 150){ + /* UTC Time */ + char utc_str[ASN_UTC_TIME_SIZE]; + data_len = ASN_UTC_TIME_SIZE -1 + 2; + + if (len < data_len) + return BUFFER_E; + + if (ts->tm_year >= 50 && ts->tm_year < 100){ + year = ts->tm_year; + } else if (ts->tm_year >= 100 && ts->tm_year < 150){ + year = ts->tm_year - 100; + } + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + min = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE, + "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, min, sec); + *data_ptr = (byte) ASN_UTC_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_UTC_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE - 1); + + } else { + /* GeneralizedTime */ + char gt_str[ASN_GENERALIZED_TIME_SIZE]; + data_len = ASN_GENERALIZED_TIME_SIZE + 1; + + if (len < data_len) + return BUFFER_E; + + year = ts->tm_year + 1900; + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + min = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE, + "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, min, sec); + *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE - 1); + } + + return data_len; +} + +#endif /* !NO_ASN_TIME && HAVE_PKCS7 */ + + #if defined(USE_WOLF_VALIDDATE) /* to the second */ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 64557907c..87eeeb8a7 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -575,7 +575,7 @@ typedef struct ESD { byte signerDigAlgoId[MAX_ALGO_SZ]; byte digEncAlgoId[MAX_ALGO_SZ]; byte signedAttribSet[MAX_SET_SZ]; - EncodedAttrib signedAttribs[6]; + EncodedAttrib signedAttribs[7]; byte signerDigest[MAX_OCTET_STR_SZ]; word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz; word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, @@ -751,11 +751,18 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, const byte* contentTypeOid, word32 contentTypeOidSz, const byte* contentType, word32 contentTypeSz, - const byte* messageDigestOid, word32 messageDigestOidSz) + const byte* messageDigestOid, word32 messageDigestOidSz, + const byte* signingTimeOid, word32 signingTimeOidSz) { int hashSz; +#ifdef NO_ASN_TIME PKCS7Attrib cannedAttribs[2]; +#else + PKCS7Attrib cannedAttribs[3]; + byte signingTime[MAX_TIME_STRING_SZ]; + int signingTimeSz; +#endif word32 cannedAttribsCount; if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL || @@ -766,6 +773,12 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, if (hashSz < 0) return hashSz; +#ifndef NO_ASN_TIME + signingTimeSz = GetAsnTimeString(signingTime, sizeof(signingTime)); + if (signingTimeSz < 0) + return signingTimeSz; +#endif + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); cannedAttribs[0].oid = contentTypeOid; @@ -776,14 +789,25 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, cannedAttribs[1].oidSz = messageDigestOidSz; cannedAttribs[1].value = esd->contentDigest; cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ +#ifndef NO_ASN_TIME + cannedAttribs[2].oid = signingTimeOid; + cannedAttribs[2].oidSz = signingTimeOidSz; + cannedAttribs[2].value = (byte*)signingTime; + cannedAttribs[2].valueSz = signingTimeSz; +#endif esd->signedAttribsCount += cannedAttribsCount; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 3, cannedAttribs, cannedAttribsCount); esd->signedAttribsCount += pkcs7->signedAttribsSz; +#ifdef NO_ASN_TIME esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, pkcs7->signedAttribs, pkcs7->signedAttribsSz); +#else + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[3], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); +#endif return 0; } @@ -1074,6 +1098,11 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 }; + /* signingTime OID () */ + byte signingTimeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x05}; + word32 signerInfoSz = 0; word32 totalSz, total2Sz; int idx = 0, ret = 0; @@ -1198,7 +1227,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, contentTypeOid, sizeof(contentTypeOid), pkcs7->contentType, pkcs7->contentTypeSz, - messageDigestOid, sizeof(messageDigestOid)); + messageDigestOid, sizeof(messageDigestOid), + signingTimeOid, sizeof(signingTimeOid)); if (ret < 0) { return MEMORY_E; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 82ef21871..a026d8787 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -305,7 +305,8 @@ enum Misc_ASN { TRAILING_ZERO = 1, /* Used for size of zero pad */ MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ - defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) MAX_TIME_STRING_SZ = 25, /* Max length of formatted time string */ #endif @@ -990,6 +991,9 @@ typedef struct tm wolfssl_tm; defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); #endif +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) +WOLFSSL_LOCAL int GetAsnTimeString(byte* buf, word32 len); +#endif WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, wolfssl_tm* certTime, int* idx); WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType);