std::vector GcmWrapper::Encrypt()

in azure-protected-vm-secrets/Windows/BcryptAesWrapper.cpp [227:323]


std::vector<unsigned char> GcmWrapper::Encrypt(const std::vector<unsigned char> &data, AesChainingInfo *chainingInfo) const
{
    DWORD bytesDone = 0;
    long long ciphertextSize = 0;
    long long ptxOffset = 0;
    if (chainingInfo == nullptr) {
        throw std::exception("Chaining info must be set before calling Encrypt");
    }
    long long dataLength = data.size();
    long long encryptedDataLength = __round_up(dataLength, this->blockLength);
    long numBlocks = encryptedDataLength / this->blockLength;
    GcmChainingInfo* gcmChainingInfo = dynamic_cast<GcmChainingInfo*>(chainingInfo);
    BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO* authInfo = gcmChainingInfo->GetAuthInfo();
    encryptedDataLength += authInfo->cbTag;
    std::vector<unsigned char> result(encryptedDataLength);
    std::vector<unsigned char> initVector = gcmChainingInfo->GetInitVector();

#ifndef PLATFORM_UNIX
    NTSTATUS bcryptResult = STATUS_SUCCESS;
    // init aad
    bcryptResult = BCryptEncrypt(
        this->hAesKey,
        nullptr,
        0,
        authInfo,
        initVector.data(),
        initVector.size(),
        nullptr,
        0,
        &bytesDone,
        0
    );
    if (STATUS_SUCCESS != bcryptResult) {
		// CryptographyError class, AES subclass, encryptError
        throw BcryptError(bcryptResult, "BCryptEncrypt failed",
            ErrorCode::CryptographyError_AES_encryptError);
    }

    authInfo->cbAuthData = 0;
    authInfo->pbAuthData = nullptr;
    
    for (long i = 0; i < numBlocks - 1; i++) {
        bytesDone = 0;
        bcryptResult = BCryptEncrypt(
            this->hAesKey,
            (unsigned char *)data.data() + ptxOffset,
            this->blockLength,
            authInfo,
            initVector.data(),
            initVector.size(),
            result.data() + ciphertextSize,
            this->blockLength,
            &bytesDone,
            0
        );
        if (STATUS_SUCCESS != bcryptResult) {
            // CryptographyError class, AES subclass, encryptError
            throw BcryptError(bcryptResult, "BCryptEncrypt failed",
                ErrorCode::CryptographyError_AES_encryptError);
        }
        ciphertextSize += this->blockLength;
        ptxOffset += bytesDone;
    }
    bytesDone = 0;
    authInfo->dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG;

    bcryptResult = BCryptEncrypt(
        this->hAesKey,
        (unsigned char*)data.data() + ptxOffset,
        data.size() - ptxOffset,
        authInfo,
        initVector.data(),
        initVector.size(),
        result.data() + ciphertextSize,
        this->blockLength,
        &bytesDone,
        0
    );
    if (STATUS_SUCCESS != bcryptResult) {
        // CryptographyError class, AES subclass, encryptError
        throw BcryptError(bcryptResult, "BCryptEncrypt failed",
            ErrorCode::CryptographyError_AES_encryptError);
    }
    ciphertextSize += bytesDone;

    result.resize(ciphertextSize + authInfo->cbTag);

    std::copy(
        authInfo->pbTag,
        authInfo->pbTag + authInfo->cbTag,
        result.data() + ciphertextSize
    );
    
#else
#endif // !PLATFORM_UNIX
    return result;
}