FreeRTOS-Plus/ThirdParty/WolfSSL-FIPS-Ready/wolfcrypt/src/asn.c
/* Convert a BER encoding with indefinite length items to DER.
 *
 * ber    BER encoded data.
 * berSz  Length of BER encoded data.
 * der    Buffer to hold DER encoded version of data.
 *        NULL indicates only the length is required.
 * derSz  The size of the buffer to hold the DER encoded data.
 *        Will be set if der is NULL, otherwise the value is checked as der is
 *        filled.
 * returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or
 * derSz are NULL.
 */
Convert a BER encoding with indefinite length items to DER.
ber    BER encoded data.
berSz  Length of BER encoded data.
der    Buffer to hold DER encoded version of data.
NULL indicates only the length is required.
derSz  The size of the buffer to hold the DER encoded data.
Will be set if der is NULL, otherwise the value is checked as der is
filled.
returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or
derSz are NULL.
Convert a BER encoding with indefinite length items to DER . ber BER encoded data . berSz Length of BER encoded data . der Buffer to hold DER encoded version of data . NULL indicates only the length is required . derSz The size of the buffer to hold the DER encoded data . Will be set if der is NULL otherwise the value is checked as der is filled . returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or derSz are NULL .
int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz)
{
    int ret = 0;
    word32 i, j;
#ifdef WOLFSSL_SMALL_STACK
    IndefItems* indefItems = NULL;
#else
    IndefItems indefItems[1];
#endif
    byte tag, basic;
    word32 length;
    int indef;
    if (ber == NULL || derSz == NULL)
        return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
    indefItems = XMALLOC(sizeof(IndefItems), NULL, DYNAMIC_TYPE_TMP_BUFFER);
    if (indefItems == NULL) {
        ret = MEMORY_E;
        goto end;
    }
#endif
    XMEMSET(indefItems, 0, sizeof(*indefItems));
    for (i = 0; i < berSz; ) {
        word32 start = i;
        ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
        if (ret != 0) {
            goto end;
        }
        if (indef) {
            ret = IndefItems_AddItem(indefItems, i);
            if (ret != 0) {
                goto end;
            }
            if ((tag & 0xC0) == 0 &&
                tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
                tag != (ASN_SET      | ASN_CONSTRUCTED)) {
                basic = tag & (~ASN_CONSTRUCTED);
                for (; i < berSz; ) {
                    ret = GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
                    if (ret != 0) {
                        goto end;
                    }
                    if (tag == ASN_EOC) {
                        if (length != 0) {
                            ret = ASN_PARSE_E;
                            goto end;
                        }
                        break;
                    }
                    if (indef || tag != basic) {
                        ret = ASN_PARSE_E;
                        goto end;
                    }
                    IndefItems_AddData(indefItems, length);
                    i += length;
                }
                if (tag != ASN_EOC) {
                    ret = ASN_PARSE_E;
                    goto end;
                }
                IndefItems_UpdateHeaderLen(indefItems);
                IndefItems_Up(indefItems);
            }
        }
        else if (tag == ASN_EOC) {
            if (length != 0) {
                ret = ASN_PARSE_E;
                goto end;
            }
            if (indefItems->depth == 0) {
                ret = ASN_PARSE_E;
                goto end;
            }
            IndefItems_CalcLength(indefItems);
            IndefItems_Up(indefItems);
        }
        else {
            if (i + length > berSz) {
                ret = ASN_PARSE_E;
                goto end;
            }
            i += length;
            IndefItems_MoreData(indefItems, i - start);
        }
    }
    if (indefItems->depth != 0) {
        ret = ASN_PARSE_E;
        goto end;
    }
    j = 0;
    indefItems->idx = 0;
    for (i = 0; i < berSz; ) {
        word32 start = i;
        (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
        if (indef) {
            if (der != NULL) {
                if (j + IndefItems_HeaderLen(indefItems) > *derSz) {
                    ret = BUFFER_E;
                    goto end;
                }
                if ((tag & 0xC0) == 0 &&
                    tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
                    tag != (ASN_SET      | ASN_CONSTRUCTED)) {
                    tag &= ~ASN_CONSTRUCTED;
                }
                der[j] = tag;
                (void)SetLength(IndefItems_Len(indefItems), der + j + 1);
            }
            j += IndefItems_HeaderLen(indefItems);
            if ((tag & 0xC0) == 0 &&
                tag != (ASN_SEQUENCE | ASN_CONSTRUCTED) &&
                tag != (ASN_SET      | ASN_CONSTRUCTED)) {
                for (; i < berSz; ) {
                    (void)GetBerHeader(ber, &i, berSz, &tag, &length, &indef);
                    if (tag == ASN_EOC) {
                        break;
                    }
                    if (der != NULL) {
                        if (j + length > *derSz) {
                            ret = BUFFER_E;
                            goto end;
                        }
                        XMEMCPY(der + j, ber + i, length);
                    }
                    j += length;
                    i += length;
                }
            }
            indefItems->idx++;
        }
        else if (tag == ASN_EOC) {
        }
        else {
            i += length;
            if (der != NULL) {
                if (j + i - start > *derSz) {
                    ret = BUFFER_E;
                    goto end;
                }
                XMEMCPY(der + j, ber + start, i - start);
            }
            j += i - start;
        }
    }
    *derSz = j;
    if (der == NULL) {
        ret = LENGTH_ONLY_E;
    }
end:
#ifdef WOLFSSL_SMALL_STACK
    if (indefItems != NULL) {
        XFREE(indefItems, NULL, DYNAMIC_TYPE_TMP_BUFFER);
    }
#endif
    return ret;
}
int wc_BerToDer ( const byte * ber , word32 berSz , byte * der , word32 * derSz ) { int ret = 0 ; word32 i , j ; #ifdef WOLFSSL_SMALL_STACK IndefItems * indefItems = NULL ; #else IndefItems indefItems [ 1 ] ; #endif byte tag , basic ; word32 length ; int indef ; if ( ber == NULL || derSz == NULL ) return BAD_FUNC_ARG ; #ifdef WOLFSSL_SMALL_STACK indefItems = XMALLOC ( sizeof ( IndefItems ) , NULL , DYNAMIC_TYPE_TMP_BUFFER ) ; if ( indefItems == NULL ) { ret = MEMORY_E ; goto end ; } #endif XMEMSET ( indefItems , 0 , sizeof ( * indefItems ) ) ; for ( i = 0 ; i < berSz ; ) { word32 start = i ; ret = GetBerHeader ( ber , & i , berSz , & tag , & length , & indef ) ; if ( ret != 0 ) { goto end ; } if ( indef ) { ret = IndefItems_AddItem ( indefItems , i ) ; if ( ret != 0 ) { goto end ; } if ( ( tag & 0xC0 ) == 0 && tag != ( ASN_SEQUENCE | ASN_CONSTRUCTED ) && tag != ( ASN_SET | ASN_CONSTRUCTED ) ) { basic = tag & ( ~ ASN_CONSTRUCTED ) ; for ( ; i < berSz ; ) { ret = GetBerHeader ( ber , & i , berSz , & tag , & length , & indef ) ; if ( ret != 0 ) { goto end ; } if ( tag == ASN_EOC ) { if ( length != 0 ) { ret = ASN_PARSE_E ; goto end ; } break ; } if ( indef || tag != basic ) { ret = ASN_PARSE_E ; goto end ; } IndefItems_AddData ( indefItems , length ) ; i += length ; } if ( tag != ASN_EOC ) { ret = ASN_PARSE_E ; goto end ; } IndefItems_UpdateHeaderLen ( indefItems ) ; IndefItems_Up ( indefItems ) ; } } else if ( tag == ASN_EOC ) { if ( length != 0 ) { ret = ASN_PARSE_E ; goto end ; } if ( indefItems -> depth == 0 ) { ret = ASN_PARSE_E ; goto end ; } IndefItems_CalcLength ( indefItems ) ; IndefItems_Up ( indefItems ) ; } else { if ( i + length > berSz ) { ret = ASN_PARSE_E ; goto end ; } i += length ; IndefItems_MoreData ( indefItems , i - start ) ; } } if ( indefItems -> depth != 0 ) { ret = ASN_PARSE_E ; goto end ; } j = 0 ; indefItems -> idx = 0 ; for ( i = 0 ; i < berSz ; ) { word32 start = i ; ( void ) GetBerHeader ( ber , & i , berSz , & tag , & length , & indef ) ; if ( indef ) { if ( der != NULL ) { if ( j + IndefItems_HeaderLen ( indefItems ) > * derSz ) { ret = BUFFER_E ; goto end ; } if ( ( tag & 0xC0 ) == 0 && tag != ( ASN_SEQUENCE | ASN_CONSTRUCTED ) && tag != ( ASN_SET | ASN_CONSTRUCTED ) ) { tag &= ~ ASN_CONSTRUCTED ; } der [ j ] = tag ; ( void ) SetLength ( IndefItems_Len ( indefItems ) , der + j + 1 ) ; } j += IndefItems_HeaderLen ( indefItems ) ; if ( ( tag & 0xC0 ) == 0 && tag != ( ASN_SEQUENCE | ASN_CONSTRUCTED ) && tag != ( ASN_SET | ASN_CONSTRUCTED ) ) { for ( ; i < berSz ; ) { ( void ) GetBerHeader ( ber , & i , berSz , & tag , & length , & indef ) ; if ( tag == ASN_EOC ) { break ; } if ( der != NULL ) { if ( j + length > * derSz ) { ret = BUFFER_E ; goto end ; } XMEMCPY ( der + j , ber + i , length ) ; } j += length ; i += length ; } } indefItems -> idx ++ ; } else if ( tag == ASN_EOC ) { } else { i += length ; if ( der != NULL ) { if ( j + i - start > * derSz ) { ret = BUFFER_E ; goto end ; } XMEMCPY ( der + j , ber + start , i - start ) ; } j += i - start ; } } * derSz = j ; if ( der == NULL ) { ret = LENGTH_ONLY_E ; } end : #ifdef WOLFSSL_SMALL_STACK if ( indefItems != NULL ) { XFREE ( indefItems , NULL , DYNAMIC_TYPE_TMP_BUFFER ) ; } #endif return ret ; }
Convert a BER encoding with indefinite length items to DER.
Convert a BER encoding with indefinite length items to DER .
/* Calculate indefinite item lengths */ /* Get next BER item */ /* Indefinite item - add to list */ /* Constructed basic type - get repeating tag */ /* Add up lengths of each item below */ /* Get next BER_item */ /* End of content closes item */ /* Must be zero length */ /* Must not be indefinite and tag must match parent */ /* Add to length */ /* Skip data */ /* Ensure we got an EOC and not end of data */ /* Set the header length to include the length field */ /* Go to indefinte parent item */ /* End-of-content must be 0 length */ /* Check there is an item to close - missing EOC */ /* Finish calculation of data length for indefinite item */ /* Go to indefinte parent item */ /* Known length item to add in - make sure enough data for it */ /* Include all data - can't have indefinite inside definite */ /* Add entire item to current indefinite item */ /* Check we had a EOC for each indefinite item */ /* Write out DER */ /* Reset index */ /* Get item - checked above */ /* Check enough space for header */ /* Remove constructed tag for basic types */ /* Add tag and length */ /* Add header length of indefinite item */ /* For basic type - get each child item and add data */ /* Move to next indef item in list */ /* End-Of-Content is not written out in DER */ /* Write out definite length item as is. */ /* Ensure space for item */ /* Copy item as is */ /* Return the length of the DER encoded ASN.1 */