Change wc_BerToDer signature to have length as param

Clean up code to make readable
This commit is contained in:
Sean Parkinson
2018-02-20 09:49:56 +10:00
parent d09f26a69f
commit 6dad94c0fa
3 changed files with 144 additions and 60 deletions

View File

@ -790,29 +790,42 @@ static word32 SetBitString(word32 len, byte unusedBits, byte* output)
/* Convert a BER encoding with indefinite length items to DER.
*
* ber BER encoded data.
* length Length of BER encoded data.
* berSz Length of BER encoded data.
* der Buffer to hold DER encoded version of data.
* NULL indicates only the length is required.
* 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.
* derSz The size of the buffer to hold the DER encoded data.
* Will be set if der is NULL, otherwise the value is checked as der is
* filled.
* returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or
* derSz are NULL.
*/
int wc_BerToDer(byte* ber, word32 length, byte* der)
int wc_BerToDer(byte* ber, word32 berSz, byte* der, word32* derSz)
{
int ret;
word32 i, j, k;
int len, l;
int indef;
int depth = 1;
word32 cnt;
byte type;
word32 cnt, sz;
word32 outSz;
byte lenBytes[4];
if (ber == NULL)
if (ber == NULL || derSz == NULL)
return BAD_FUNC_ARG;
for (i = 0, j = 0; i < length; ) {
if (i + 1 >= length)
outSz = *derSz;
for (i = 0, j = 0; i < berSz; ) {
/* Check that there is data for an ASN item to parse. */
if (i + 1 > berSz)
return ASN_PARSE_E;
/* End Of Content (EOC) mark end of indefinite length items.
* EOCs are not encoded in DER.
* Keep track of no. indefinite length items that have not been
* terminated in depth.
*/
if (ber[i] == 0 && ber[i+1] == 0) {
if (--depth == 0)
break;
@ -821,90 +834,155 @@ int wc_BerToDer(byte* ber, word32 length, byte* der)
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;
/* Indefinite length is encoded as: 0x80 */
type = ber[i];
indef = ber[i+1] == ASN_INDEF_LENGTH;
if (indef && (type & 0xC0) == 0 &&
ber[i] != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
ber[i] != (ASN_SET | ASN_CONSTRUCTED)) {
/* Indefinite length OCTET STRING or other simple type.
* Put all the data into one entry.
*/
/* Type no longer constructed. */
type &= ~ASN_CONSTRUCTED;
if (der != NULL) {
/* Ensure space for type. */
if (j + 1 >= outSz)
return BUFFER_E;
der[j] = type;
}
i++; j++;
/* Skip indefinite length. */
i++;
if (i + 1 >= length)
/* There must be further ASN1 items to combine. */
if (i + 1 >= berSz)
return ASN_PARSE_E;
/* Calculate length of combined data. */
len = 0;
k = i;
while (ber[k] != 0x00) {
/* Each ASN item must be the same type as the constructed. */
if (ber[k] != type)
return ASN_PARSE_E;
k++;
ret = GetLength(ber, &k, &l, length);
ret = GetLength(ber, &k, &l, berSz);
if (ret < 0)
return ASN_PARSE_E;
k += l;
len += l;
if (k + 1 >= length)
/* Must at least have terminating EOC. */
if (k + 1 >= berSz)
return ASN_PARSE_E;
}
/* Ensure a valid EOC ASN item. */
if (ber[k+1] != 0x00)
return ASN_PARSE_E;
if (der == NULL) {
/* Add length of ASN item length encoding and data. */
j += SetLength(len, lenBytes);
j += len;
}
else {
/* Check space for encoded length. */
if (SetLength(len, lenBytes) > outSz - j)
return BUFFER_E;
/* Encode new length. */
j += SetLength(len, der + j);
/* Encode data in single item. */
k = i;
while (ber[k] != 0x00) {
/* Skip ASN type. */
k++;
ret = GetLength(ber, &k, &l, length);
/* Find length of data in ASN item. */
ret = GetLength(ber, &k, &l, berSz);
if (ret < 0)
return ASN_PARSE_E;
/* Ensure space for data and copy in. */
if (j + l > outSz)
return BUFFER_E;
XMEMCPY(der + j, ber + k, l);
k += l; j += l;
}
}
/* Continue conversion after EOC. */
i = k + 2;
continue;
}
if (der != NULL)
if (der != NULL) {
/* Ensure space for type and at least one byte of length. */
if (j + 1 >= outSz)
return BUFFER_E;
/* Put in type. */
der[j] = ber[i];
}
i++; j++;
if (indef) {
/* Skip indefinite length. */
i++;
/* Calculate the size of the data inside constructed. */
ret = wc_BerToDer(ber + i, berSz - i, NULL, &sz);
if (ret != LENGTH_ONLY_E)
return ret;
if (der != NULL) {
/* Ensure space for encoded length. */
if (SetLength(sz, lenBytes) > outSz - j)
return BUFFER_E;
/* Encode real length. */
j += SetLength(sz, der + j);
}
else {
/* Add size of encoded length. */
j += SetLength(sz, lenBytes);
}
/* Another EOC to find. */
depth++;
}
else {
/* Get the size of the encode length and length value. */
cnt = i;
ret = GetLength(ber, &cnt, &len, length);
ret = GetLength(ber, &cnt, &len, berSz);
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)
/* Check there is enough data to copy out. */
if (i + cnt + len > berSz)
return ASN_PARSE_E;
if (der != NULL)
XMEMCPY(der + j, ber + i, len);
i += len;
j += len;
if (der != NULL) {
/* Ensure space in DER buffer. */
if (j + cnt + len > outSz)
return BUFFER_E;
/* Copy length and data into DER buffer. */
XMEMCPY(der + j, ber + i, cnt + len);
}
/* Continue conversion after this ASN item. */
i += cnt + len;
j += cnt + len;
}
else
depth++;
}
return j;
/* Return length if no buffer to write to. */
if (der == NULL) {
*derSz = j;
return LENGTH_ONLY_E;
}
return 0;
}
#endif

View File

@ -1856,15 +1856,17 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
if (length == 0 && pkiMsg[idx-1] == 0x80) {
#ifdef ASN_BER_TO_DER
int len;
word32 len;
len = wc_BerToDer(pkiMsg, pkiMsgSz, NULL);
if (len < 0)
return len;
ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
if (ret != LENGTH_ONLY_E)
return ret;
pkcs7->der = XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
if (pkcs7->der == NULL)
return MEMORY_E;
wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der);
ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
if (ret < 0)
return ret;
pkiMsg = pkcs7->der;
pkiMsgSz = len;
@ -4343,15 +4345,17 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
if (length == 0 && pkiMsg[idx-1] == 0x80) {
#ifdef ASN_BER_TO_DER
int len;
word32 len;
len = wc_BerToDer(pkiMsg, pkiMsgSz, NULL);
if (len < 0)
return len;
ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
if (ret != LENGTH_ONLY_E)
return ret;
pkcs7->der = XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
if (pkcs7->der == NULL)
return MEMORY_E;
wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der);
ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
if (ret < 0)
return ret;
pkiMsg = pkcs7->der;
pkiMsgSz = len;

View File

@ -86,7 +86,8 @@ enum ASN_Tags {
ASN_GENERALIZED_TIME = 0x18,
CRL_EXTENSIONS = 0xa0,
ASN_EXTENSIONS = 0xa3,
ASN_LONG_LENGTH = 0x80
ASN_LONG_LENGTH = 0x80,
ASN_INDEF_LENGTH = 0x80
};
#define ASN_UTC_TIME_SIZE 14
@ -765,7 +766,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 int wc_BerToDer(byte* ber, word32 berSz, byte* der,
word32* derSz);
WOLFSSL_ASN_API void FreeAltNames(DNS_entry*, void*);
#ifndef IGNORE_NAME_CONSTRAINTS