mirror of https://github.com/wolfSSL/wolfssl.git
Support indefinite length BER encodings in PKCS #7
parent
7a2aa6bc13
commit
d09f26a69f
15
configure.ac
15
configure.ac
|
@ -217,6 +217,7 @@ then
|
|||
enable_aeskeywrap=yes
|
||||
enable_x963kdf=yes
|
||||
enable_scrypt=yes
|
||||
enable_indef=yes
|
||||
|
||||
AM_CFLAGS="-DHAVE_AES_DECRYPT $AM_CFLAGS"
|
||||
fi
|
||||
|
@ -2662,6 +2663,19 @@ fi
|
|||
AM_CONDITIONAL([BUILD_SRP], [test "x$ENABLED_SRP" = "xyes"])
|
||||
|
||||
|
||||
# Indefinite length encoded BER message support
|
||||
AC_ARG_ENABLE([indef],
|
||||
[AS_HELP_STRING([--enable-indef],[Enable parsing of indefinite length encoded msgs (default: disabled)])],
|
||||
[ ENABLED_BER_INDEF=$enableval ],
|
||||
[ ENABLED_BER_INDEF=no ]
|
||||
)
|
||||
|
||||
if test "x$ENABLED_BER_INDEF" = "xyes"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DASN_BER_TO_DER"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Small Stack
|
||||
AC_ARG_ENABLE([smallstack],
|
||||
|
@ -4247,6 +4261,7 @@ echo " * SIGNAL: $ENABLED_SIGNAL"
|
|||
echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS"
|
||||
echo " * DTLS: $ENABLED_DTLS"
|
||||
echo " * SCTP: $ENABLED_SCTP"
|
||||
echo " * Indefinite Length: $ENABLED_BER_INDEF"
|
||||
echo " * Multicast: $ENABLED_MCAST"
|
||||
echo " * Old TLS Versions: $ENABLED_OLD_TLS"
|
||||
echo " * SSL version 3.0: $ENABLED_SSLV3"
|
||||
|
|
|
@ -786,6 +786,128 @@ static word32 SetBitString(word32 len, byte unusedBits, byte* output)
|
|||
}
|
||||
#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */
|
||||
|
||||
#ifdef ASN_BER_TO_DER
|
||||
/* Convert a BER encoding with indefinite length items to DER.
|
||||
*
|
||||
* ber BER encoded data.
|
||||
* length Length of BER encoded data.
|
||||
* der Buffer to hold DER encoded version of data.
|
||||
* NULL indicates only the length is required.
|
||||
* returns the length of the DER data on success, ASN_PARSE_E if the BER data is
|
||||
* invalid and BAD_FUNC_ARG if ber is NULL.
|
||||
*/
|
||||
int wc_BerToDer(byte* ber, word32 length, byte* der)
|
||||
{
|
||||
int ret;
|
||||
word32 i, j, k;
|
||||
int len, l;
|
||||
int indef;
|
||||
int depth = 1;
|
||||
word32 cnt;
|
||||
byte lenBytes[4];
|
||||
|
||||
if (ber == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
for (i = 0, j = 0; i < length; ) {
|
||||
if (i + 1 >= length)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (ber[i] == 0 && ber[i+1] == 0) {
|
||||
if (--depth == 0)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
indef = ber[i+1] == 0x80;
|
||||
if (indef && ber[i] < 0x40 && ber[i] != 0x30 && ber[i] != 0x31) {
|
||||
if (der != NULL)
|
||||
der[j] = ber[i] & 0x1f;
|
||||
i++; j++;
|
||||
i++;
|
||||
|
||||
if (i + 1 >= length)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
len = 0;
|
||||
k = i;
|
||||
while (ber[k] != 0x00) {
|
||||
k++;
|
||||
ret = GetLength(ber, &k, &l, length);
|
||||
if (ret < 0)
|
||||
return ASN_PARSE_E;
|
||||
k += l;
|
||||
len += l;
|
||||
|
||||
if (k + 1 >= length)
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (der == NULL) {
|
||||
j += SetLength(len, lenBytes);
|
||||
j += len;
|
||||
}
|
||||
else {
|
||||
j += SetLength(len, der + j);
|
||||
k = i;
|
||||
while (ber[k] != 0x00) {
|
||||
k++;
|
||||
ret = GetLength(ber, &k, &l, length);
|
||||
if (ret < 0)
|
||||
return ASN_PARSE_E;
|
||||
XMEMCPY(der + j, ber + k, l);
|
||||
k += l; j += l;
|
||||
}
|
||||
}
|
||||
i = k + 2;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (der != NULL)
|
||||
der[j] = ber[i];
|
||||
i++; j++;
|
||||
|
||||
cnt = i;
|
||||
ret = GetLength(ber, &cnt, &len, length);
|
||||
if (ret < 0)
|
||||
return ASN_PARSE_E;
|
||||
cnt -= i;
|
||||
if (der != NULL) {
|
||||
for (k = 0; k < cnt; k++)
|
||||
der[j + k] = ber[i + k];
|
||||
}
|
||||
i += cnt; j += cnt;
|
||||
if (cnt == 0) {
|
||||
i++;
|
||||
len = wc_BerToDer(ber + i, length - i, NULL);
|
||||
if (len < 0)
|
||||
return len;
|
||||
if (der != NULL)
|
||||
j += SetLength(len, der + j);
|
||||
else
|
||||
j += SetLength(len, lenBytes);
|
||||
}
|
||||
|
||||
if (!indef) {
|
||||
if (i + len > length)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (der != NULL)
|
||||
XMEMCPY(der + j, ber + i, len);
|
||||
i += len;
|
||||
j += len;
|
||||
}
|
||||
else
|
||||
depth++;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
|
||||
|
||||
#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
|
||||
|
|
|
@ -449,6 +449,9 @@ const char* wc_GetErrorString(int error)
|
|||
case PRIME_GEN_E:
|
||||
return "Unable to find a prime for RSA key";
|
||||
|
||||
case BER_INDEF_E:
|
||||
return "Unable to decode an indefinite length encoded message";
|
||||
|
||||
default:
|
||||
return "unknown error number";
|
||||
|
||||
|
|
|
@ -338,6 +338,11 @@ void wc_PKCS7_Free(PKCS7* pkcs7)
|
|||
return;
|
||||
|
||||
wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
|
||||
|
||||
#ifdef ASN_BER_TO_DER
|
||||
if (pkcs7->der != NULL)
|
||||
XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -1849,6 +1854,28 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
|||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (length == 0 && pkiMsg[idx-1] == 0x80) {
|
||||
#ifdef ASN_BER_TO_DER
|
||||
int len;
|
||||
|
||||
len = wc_BerToDer(pkiMsg, pkiMsgSz, NULL);
|
||||
if (len < 0)
|
||||
return len;
|
||||
pkcs7->der = XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
if (pkcs7->der == NULL)
|
||||
return MEMORY_E;
|
||||
wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der);
|
||||
|
||||
pkiMsg = pkcs7->der;
|
||||
pkiMsgSz = len;
|
||||
idx = 0;
|
||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
#else
|
||||
return BER_INDEF_E;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get the contentInfo contentType */
|
||||
if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
@ -4299,6 +4326,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
|
|||
int encryptedContentSz;
|
||||
byte padLen;
|
||||
byte* encryptedContent = NULL;
|
||||
int explicitOctet;
|
||||
|
||||
if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
|
||||
pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL ||
|
||||
|
@ -4313,6 +4341,28 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
|
|||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
if (length == 0 && pkiMsg[idx-1] == 0x80) {
|
||||
#ifdef ASN_BER_TO_DER
|
||||
int len;
|
||||
|
||||
len = wc_BerToDer(pkiMsg, pkiMsgSz, NULL);
|
||||
if (len < 0)
|
||||
return len;
|
||||
pkcs7->der = XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
if (pkcs7->der == NULL)
|
||||
return MEMORY_E;
|
||||
wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der);
|
||||
|
||||
pkiMsg = pkcs7->der;
|
||||
pkiMsgSz = len;
|
||||
idx = 0;
|
||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
#else
|
||||
return BER_INDEF_E;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
|
@ -4435,13 +4485,17 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
|
|||
XMEMCPY(tmpIv, &pkiMsg[idx], length);
|
||||
idx += length;
|
||||
|
||||
explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0);
|
||||
|
||||
/* read encryptedContent, cont[0] */
|
||||
if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) {
|
||||
if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) &&
|
||||
pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7);
|
||||
#endif
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
idx++;
|
||||
|
||||
if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
|
@ -4450,6 +4504,22 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
|
|||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (explicitOctet) {
|
||||
if (pkiMsg[idx++] != ASN_OCTET_STRING) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7);
|
||||
#endif
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7);
|
||||
#endif
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
}
|
||||
|
||||
encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (encryptedContent == NULL) {
|
||||
|
|
|
@ -16702,6 +16702,9 @@ int pkcs7encrypted_test(void)
|
|||
pkcs7.unprotectedAttribs = testVectors[i].attribs;
|
||||
pkcs7.unprotectedAttribsSz = testVectors[i].attribsSz;
|
||||
pkcs7.heap = HEAP_HINT;
|
||||
#ifdef ASN_BER_TO_DER
|
||||
pkcs7.der = NULL;
|
||||
#endif
|
||||
|
||||
/* encode encryptedData */
|
||||
encryptedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted,
|
||||
|
|
|
@ -765,6 +765,8 @@ struct TrustedPeerCert {
|
|||
#define WOLFSSL_ASN_API WOLFSSL_LOCAL
|
||||
#endif
|
||||
|
||||
WOLFSSL_ASN_API int wc_BerToDer(byte* ber, word32 length, byte* der);
|
||||
|
||||
WOLFSSL_ASN_API void FreeAltNames(DNS_entry*, void*);
|
||||
#ifndef IGNORE_NAME_CONSTRAINTS
|
||||
WOLFSSL_ASN_API void FreeNameSubtrees(Base_entry*, void*);
|
||||
|
|
|
@ -198,7 +198,9 @@ enum {
|
|||
PSS_SALTLEN_E = -250, /* PSS length of salt is to long for hash */
|
||||
PRIME_GEN_E = -251, /* Failure finding a prime. */
|
||||
|
||||
WC_LAST_E = -251, /* Update this to indicate last error */
|
||||
BER_INDEF_E = -252, /* Cannot decode indefinite length BER. */
|
||||
|
||||
WC_LAST_E = -252, /* Update this to indicate last error */
|
||||
MIN_CODE_E = -300 /* errors -101 - -299 */
|
||||
|
||||
/* add new companion error id strings for any new error codes
|
||||
|
|
|
@ -100,6 +100,9 @@ typedef struct PKCS7 {
|
|||
byte* issuer; /* issuer name of singleCert */
|
||||
byte* privateKey; /* private key, DER, not owner */
|
||||
void* heap; /* heap hint for dynamic memory */
|
||||
#ifdef ASN_BER_TO_DER
|
||||
byte* der; /* DER encoded version of message */
|
||||
#endif
|
||||
byte* cert[MAX_PKCS7_CERTS];
|
||||
|
||||
/* Encrypted-data Content Type */
|
||||
|
|
Loading…
Reference in New Issue