FreeRTOS-Plus/ThirdParty/WolfSSL-FIPS-Ready/wolfcrypt/src/asn.c
/* encrypt PKCS 12 content
 *
 * NOTE: if out is NULL then outSz is set with the total buffer size needed and
 *       the error value LENGTH_ONLY_E is returned.
 *
 * input      data to encrypt
 * inputSz    size of input buffer
 * out        buffer to hold the result
 * outSz      size of out buffer
 * password   password if used. Can be NULL for no password
 * passwordSz size of password buffer
 * vPKCS      version of PKCS i.e. PKCS5v2
 * vAlgo      algorithm version
 * salt       buffer holding salt if used. If NULL then a random salt is created
 * saltSz     size of salt buffer if it is not NULL
 * itt        number of iterations used
 * rng        random number generator to use
 * heap       possible heap hint for mallocs/frees
 *
 * returns the total size of encrypted content on success.
 *
 * data returned is :
 * [ seq - obj [ seq -salt,itt]] , construct with encrypted data
 */
encrypt PKCS 12 content
NOTE: if out is NULL then outSz is set with the total buffer size needed and
the error value LENGTH_ONLY_E is returned.

input      data to encrypt
inputSz    size of input buffer
out        buffer to hold the result
outSz      size of out buffer
password   password if used. Can be NULL for no password
passwordSz size of password buffer
vPKCS      version of PKCS i.e. PKCS5v2
vAlgo      algorithm version
salt       buffer holding salt if used. If NULL then a random salt is created
saltSz     size of salt buffer if it is not NULL
itt        number of iterations used
rng        random number generator to use
heap       possible heap hint for mallocs/frees

returns the total size of encrypted content on success.

data returned is :
[ seq - obj [ seq -salt,itt]] , construct with encrypted data
encrypt PKCS 12 content NOTE : if out is NULL then outSz is set with the total buffer size needed and the error value LENGTH_ONLY_E is returned . input data to encrypt inputSz size of input buffer out buffer to hold the result outSz size of out buffer password password if used . Can be NULL for no password passwordSz size of password buffer vPKCS version of PKCS i . e . PKCS5v2 vAlgo algorithm version salt buffer holding salt if used . If NULL then a random salt is created saltSz size of salt buffer if it is not NULL itt number of iterations used rng random number generator to use heap possible heap hint for mallocs / frees returns the total size of encrypted content on success . data returned is : [ seq - obj [ seq - salt itt ]] construct with encrypted data
int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz,
        const char* password, int passwordSz, int vPKCS, int vAlgo,
        byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap)
{
    word32 sz;
    word32 inOutIdx = 0;
    word32 tmpIdx   = 0;
    word32 totalSz  = 0;
    word32 seqSz;
    word32 innerSz;
    int    ret;
    int    version, id, blockSz = 0;
#ifdef WOLFSSL_SMALL_STACK
    byte*  saltTmp = NULL;
    byte*  cbcIv   = NULL;
#else
    byte   saltTmp[MAX_SALT_SIZE];
    byte   cbcIv[MAX_IV_SIZE];
#endif
    byte   seq[MAX_SEQ_SZ];
    byte   shr[MAX_SHORT_SZ];
    word32 maxShr = MAX_SHORT_SZ;
    word32 algoSz;
    const  byte* algoName;
    (void)heap;
    WOLFSSL_ENTER("EncryptContent()");
    if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0)
        return ASN_INPUT_E;  
    if (version == PKCS5v2) {
        WOLFSSL_MSG("PKCS#5 version 2 not supported yet");
        return BAD_FUNC_ARG;
    }
    if (saltSz > MAX_SALT_SIZE)
        return ASN_PARSE_E;
    if (outSz == NULL) {
        return BAD_FUNC_ARG;
    }
    sz = Pkcs8Pad(NULL, inputSz, blockSz);
    totalSz  = ASN_TAG_SZ;
    totalSz += SetLength(sz, seq);
    totalSz += sz;
    algoName = OidFromId(id, oidPBEType, &algoSz);
    if (algoName == NULL) {
        WOLFSSL_MSG("Unknown Algorithm");
        return 0;
    }
    innerSz = SetObjectId(algoSz, seq);
    innerSz += algoSz;
    if (salt == NULL || saltSz == 0) {
        sz = 8;
    }
    else {
        sz = saltSz;
    }
    seqSz  = SetOctetString(sz, seq);
    seqSz += sz;
    tmpIdx = 0;
    seqSz += SetShortInt(shr, &tmpIdx, itt, maxShr);
    innerSz += seqSz + SetSequence(seqSz, seq);
    totalSz += innerSz + SetSequence(innerSz, seq);
    if (out == NULL) {
        *outSz = totalSz;
        return LENGTH_ONLY_E;
    }
    inOutIdx = 0;
    if (totalSz > *outSz)
        return BUFFER_E;
    inOutIdx += SetSequence(innerSz, out + inOutIdx);
    inOutIdx += SetObjectId(algoSz, out + inOutIdx);
    XMEMCPY(out + inOutIdx, algoName, algoSz);
    inOutIdx += algoSz;
    inOutIdx += SetSequence(seqSz, out + inOutIdx);
    if (salt == NULL || saltSz == 0) {
        saltSz = 8;
    #ifdef WOLFSSL_SMALL_STACK
        saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER);
        if (saltTmp == NULL)
            return MEMORY_E;
    #endif
        salt = saltTmp;
        if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) {
            WOLFSSL_MSG("Error generating random salt");
        #ifdef WOLFSSL_SMALL_STACK
            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
        #endif
            return ret;
        }
    }
    inOutIdx += SetOctetString(saltSz, out + inOutIdx);
    if (saltSz + inOutIdx > *outSz) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
    #endif
        return BUFFER_E;
    }
    XMEMCPY(out + inOutIdx, salt, saltSz);
    inOutIdx += saltSz;
    ret = SetShortInt(out, &inOutIdx, itt, *outSz);
    if (ret < 0) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
    #endif
        return ret;
    }
    if (inOutIdx + 1 > *outSz) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
    #endif
        return BUFFER_E;
    }
    out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0;
    sz = Pkcs8Pad(NULL, inputSz, blockSz);
    if (sz + inOutIdx > *outSz) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
    #endif
        return BUFFER_E;
    }
    inOutIdx += SetLength(sz, out + inOutIdx);
    XMEMCPY(out + inOutIdx, input, inputSz);
    sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz);
#ifdef WOLFSSL_SMALL_STACK
    cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
    if (cbcIv == NULL) {
        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
        return MEMORY_E;
    }
#endif
    if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id,
                   out + inOutIdx, sz, version, cbcIv, 1, 0)) < 0) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(cbcIv,   heap, DYNAMIC_TYPE_TMP_BUFFER);
        XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
    #endif
        return ret;  
    }
#ifdef WOLFSSL_SMALL_STACK
    XFREE(cbcIv,   heap, DYNAMIC_TYPE_TMP_BUFFER);
    XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
    (void)rng;
    return inOutIdx + sz;
}
int EncryptContent ( byte * input , word32 inputSz , byte * out , word32 * outSz , const char * password , int passwordSz , int vPKCS , int vAlgo , byte * salt , word32 saltSz , int itt , WC_RNG * rng , void * heap ) { word32 sz ; word32 inOutIdx = 0 ; word32 tmpIdx = 0 ; word32 totalSz = 0 ; word32 seqSz ; word32 innerSz ; int ret ; int version , id , blockSz = 0 ; #ifdef WOLFSSL_SMALL_STACK byte * saltTmp = NULL ; byte * cbcIv = NULL ; #else byte saltTmp [ MAX_SALT_SIZE ] ; byte cbcIv [ MAX_IV_SIZE ] ; #endif byte seq [ MAX_SEQ_SZ ] ; byte shr [ MAX_SHORT_SZ ] ; word32 maxShr = MAX_SHORT_SZ ; word32 algoSz ; const byte * algoName ; ( void ) heap ; WOLFSSL_ENTER ( " " ) ; if ( CheckAlgo ( vPKCS , vAlgo , & id , & version , & blockSz ) < 0 ) return ASN_INPUT_E ; if ( version == PKCS5v2 ) { WOLFSSL_MSG ( " " ) ; return BAD_FUNC_ARG ; } if ( saltSz > MAX_SALT_SIZE ) return ASN_PARSE_E ; if ( outSz == NULL ) { return BAD_FUNC_ARG ; } sz = Pkcs8Pad ( NULL , inputSz , blockSz ) ; totalSz = ASN_TAG_SZ ; totalSz += SetLength ( sz , seq ) ; totalSz += sz ; algoName = OidFromId ( id , oidPBEType , & algoSz ) ; if ( algoName == NULL ) { WOLFSSL_MSG ( " " ) ; return 0 ; } innerSz = SetObjectId ( algoSz , seq ) ; innerSz += algoSz ; if ( salt == NULL || saltSz == 0 ) { sz = 8 ; } else { sz = saltSz ; } seqSz = SetOctetString ( sz , seq ) ; seqSz += sz ; tmpIdx = 0 ; seqSz += SetShortInt ( shr , & tmpIdx , itt , maxShr ) ; innerSz += seqSz + SetSequence ( seqSz , seq ) ; totalSz += innerSz + SetSequence ( innerSz , seq ) ; if ( out == NULL ) { * outSz = totalSz ; return LENGTH_ONLY_E ; } inOutIdx = 0 ; if ( totalSz > * outSz ) return BUFFER_E ; inOutIdx += SetSequence ( innerSz , out + inOutIdx ) ; inOutIdx += SetObjectId ( algoSz , out + inOutIdx ) ; XMEMCPY ( out + inOutIdx , algoName , algoSz ) ; inOutIdx += algoSz ; inOutIdx += SetSequence ( seqSz , out + inOutIdx ) ; if ( salt == NULL || saltSz == 0 ) { saltSz = 8 ; #ifdef WOLFSSL_SMALL_STACK saltTmp = ( byte * ) XMALLOC ( saltSz , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; if ( saltTmp == NULL ) return MEMORY_E ; #endif salt = saltTmp ; if ( ( ret = wc_RNG_GenerateBlock ( rng , saltTmp , saltSz ) ) != 0 ) { WOLFSSL_MSG ( " " ) ; #ifdef WOLFSSL_SMALL_STACK XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; #endif return ret ; } } inOutIdx += SetOctetString ( saltSz , out + inOutIdx ) ; if ( saltSz + inOutIdx > * outSz ) { #ifdef WOLFSSL_SMALL_STACK XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; #endif return BUFFER_E ; } XMEMCPY ( out + inOutIdx , salt , saltSz ) ; inOutIdx += saltSz ; ret = SetShortInt ( out , & inOutIdx , itt , * outSz ) ; if ( ret < 0 ) { #ifdef WOLFSSL_SMALL_STACK XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; #endif return ret ; } if ( inOutIdx + 1 > * outSz ) { #ifdef WOLFSSL_SMALL_STACK XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; #endif return BUFFER_E ; } out [ inOutIdx ++ ] = ASN_CONTEXT_SPECIFIC | 0 ; sz = Pkcs8Pad ( NULL , inputSz , blockSz ) ; if ( sz + inOutIdx > * outSz ) { #ifdef WOLFSSL_SMALL_STACK XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; #endif return BUFFER_E ; } inOutIdx += SetLength ( sz , out + inOutIdx ) ; XMEMCPY ( out + inOutIdx , input , inputSz ) ; sz = Pkcs8Pad ( out + inOutIdx , inputSz , blockSz ) ; #ifdef WOLFSSL_SMALL_STACK cbcIv = ( byte * ) XMALLOC ( MAX_IV_SIZE , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; if ( cbcIv == NULL ) { XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; return MEMORY_E ; } #endif if ( ( ret = wc_CryptKey ( password , passwordSz , salt , saltSz , itt , id , out + inOutIdx , sz , version , cbcIv , 1 , 0 ) ) < 0 ) { #ifdef WOLFSSL_SMALL_STACK XFREE ( cbcIv , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; #endif return ret ; } #ifdef WOLFSSL_SMALL_STACK XFREE ( cbcIv , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; XFREE ( saltTmp , heap , DYNAMIC_TYPE_TMP_BUFFER ) ; #endif ( void ) rng ; return inOutIdx + sz ; }
encrypt PKCS 12 content
 NOTE: if out is NULL then outSz is set with the total buffer size needed and
       the error value LENGTH_ONLY_E is returned.
encrypt PKCS 12 content NOTE : if out is NULL then outSz is set with the total buffer size needed and the error value LENGTH_ONLY_E is returned .
/* Algo ID error */ /* calculate size */ /* size of constructed string at end */ /* size of sequence holding object id and sub sequence of salt and itt */ /* get subsequence of salt and itt */ /* create random salt if one not provided */ /* place iteration setting in buffer */ /* get pad size and verify buffer room */ /* copy input to output buffer and pad end */ /* encrypt */ /* encrypt failure */