diff --git a/src/fsfw/cfdp/handler/DestHandler.cpp b/src/fsfw/cfdp/handler/DestHandler.cpp
index 6ba9a918..6f4e17d0 100644
--- a/src/fsfw/cfdp/handler/DestHandler.cpp
+++ b/src/fsfw/cfdp/handler/DestHandler.cpp
@@ -432,7 +432,6 @@ void cfdp::DestHandler::finish() {
 
 ReturnValue_t cfdp::DestHandler::checksumVerification() {
   std::array<uint8_t, 1024> buf{};
-  // TODO: Checksum verification and notice of completion
   etl::crc32 crcCalc;
   uint64_t currentOffset = 0;
   FileOpParams params(transactionParams.destName.data(), transactionParams.fileSize.value());
diff --git a/src/fsfw/cfdp/handler/SourceHandler.cpp b/src/fsfw/cfdp/handler/SourceHandler.cpp
index 49570717..50d0de3d 100644
--- a/src/fsfw/cfdp/handler/SourceHandler.cpp
+++ b/src/fsfw/cfdp/handler/SourceHandler.cpp
@@ -1,8 +1,17 @@
 #include "SourceHandler.h"
 
-SourceHandler::SourceHandler(SourceHandlerParams params, FsfwSourceParams fsfwParams) {}
+#include <etl/crc32.h>
 
-void SourceHandler::fsmNacked() {
+#include <array>
+
+#include "fsfw/filesystem/HasFileSystemIF.h"
+
+using namespace returnvalue;
+
+cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwSourceParams fsfwParams)
+    : transactionParams(params.maxFilePathSize), sourceParams(std::move(params)) {}
+
+void cfdp::SourceHandler::fsmNacked() {
   if (step == TransactionStep::IDLE) {
     step = TransactionStep::TRANSACTION_START;
   }
@@ -11,7 +20,10 @@ void SourceHandler::fsmNacked() {
     step = TransactionStep::CRC_PROCEDURE;
   }
   if (step == TransactionStep::CRC_PROCEDURE) {
-    // TODO: Perform CRC procedure: Generate the CRC32 from the file.
+    ReturnValue_t result = checksumGeneration();
+    if (result != OK) {
+      // TODO: Some error handling
+    }
   }
   if (step == TransactionStep::SENDING_METADATA) {
     // TODO: Prepare and send metadata PDU
@@ -29,7 +41,7 @@ void SourceHandler::fsmNacked() {
     // TODO: Notice of completion
   }
 }
-void SourceHandler::stateMachine() {
+void cfdp::SourceHandler::stateMachine() {
   if (state == cfdp::CfdpState::IDLE) {
     return;
   }
@@ -37,3 +49,33 @@ void SourceHandler::stateMachine() {
     return fsmNacked();
   }
 }
+
+ReturnValue_t cfdp::SourceHandler::checksumGeneration() {
+  std::array<uint8_t, 1024> buf{};
+  etl::crc32 crcCalc;
+  uint64_t currentOffset = 0;
+  FileOpParams params(transactionParams.destName.data(), transactionParams.fileSize.value());
+  while (currentOffset < transactionParams.fileSize.value()) {
+    uint64_t readLen;
+    if (currentOffset + buf.size() > transactionParams.fileSize.value()) {
+      readLen = transactionParams.fileSize.value() - currentOffset;
+    } else {
+      readLen = buf.size();
+    }
+    if (readLen > 0) {
+      params.offset = currentOffset;
+      params.size = readLen;
+      auto result = sourceParams.user.vfs.readFromFile(params, buf.data(), buf.size());
+      if (result != OK) {
+        // TODO: I think this is a case for a filestore rejection, but it might sense to print
+        //       a warning or trigger an event because this should generally not happen
+        return FAILED;
+      }
+      crcCalc.add(buf.begin(), buf.begin() + readLen);
+    }
+    currentOffset += readLen;
+  }
+
+  transactionParams.crc = crcCalc.value();
+  return OK;
+}
diff --git a/src/fsfw/cfdp/handler/SourceHandler.h b/src/fsfw/cfdp/handler/SourceHandler.h
index 52299c9f..a0dc4163 100644
--- a/src/fsfw/cfdp/handler/SourceHandler.h
+++ b/src/fsfw/cfdp/handler/SourceHandler.h
@@ -2,12 +2,24 @@
 #define FSFW_CFDP_CFDPSOURCEHANDLER_H
 
 #include <cstdint>
+#include <vector>
 
+#include "UserBase.h"
 #include "defs.h"
+#include "fsfw/cfdp/FileSize.h"
+#include "fsfw/cfdp/handler/mib.h"
 #include "fsfw/events/EventReportingProxyIF.h"
 #include "fsfw/storagemanager/StorageManagerIF.h"
 
-struct SourceHandlerParams {};
+namespace cfdp {
+
+struct SourceHandlerParams {
+  SourceHandlerParams(LocalEntityCfg cfg, UserBase& user) : cfg(std::move(cfg)), user(user) {}
+
+  LocalEntityCfg cfg;
+  UserBase& user;
+  size_t maxFilePathSize = 256;
+};
 
 struct FsfwSourceParams {
   FsfwSourceParams(EventReportingProxyIF* eventReporter, StorageManagerIF& tcStore)
@@ -35,10 +47,24 @@ class SourceHandler {
     WAIT_FOR_FINISH = 7,
     NOTICE_OF_COMPLETION = 8
   };
-  cfdp::CfdpState state;
-  TransactionStep step;
+  struct TransactionParams {
+    // Initialize char vectors with length + 1 for 0 termination
+    explicit TransactionParams(size_t maxFileNameLen)
+        : sourceName(maxFileNameLen + 1), destName(maxFileNameLen + 1) {}
+
+    uint32_t crc{};
+    std::vector<char> sourceName;
+    std::vector<char> destName;
+    cfdp::FileSize fileSize;
+  } transactionParams;
+  cfdp::CfdpState state = cfdp::CfdpState::IDLE;
+  TransactionStep step = TransactionStep::IDLE;
+  SourceHandlerParams sourceParams;
 
   void fsmNacked();
+  ReturnValue_t checksumGeneration();
 };
 
+}  // namespace cfdp
+
 #endif  // FSFW_CFDP_CFDPSOURCEHANDLER_H
diff --git a/src/fsfw/cfdp/handler/UserBase.h b/src/fsfw/cfdp/handler/UserBase.h
index e367b4a8..d0ddeaa5 100644
--- a/src/fsfw/cfdp/handler/UserBase.h
+++ b/src/fsfw/cfdp/handler/UserBase.h
@@ -65,6 +65,7 @@ struct FileSegmentRecvdParams {
  */
 class UserBase {
   friend class DestHandler;
+  friend class SourceHandler;
 
  public:
   explicit UserBase(HasFileSystemIF& vfs);
diff --git a/src/fsfw/cfdp/handler/defs.h b/src/fsfw/cfdp/handler/defs.h
index b507a78d..f4d96814 100644
--- a/src/fsfw/cfdp/handler/defs.h
+++ b/src/fsfw/cfdp/handler/defs.h
@@ -1,6 +1,8 @@
 #ifndef FSFW_CFDP_HANDLER_DEFS_H
 #define FSFW_CFDP_HANDLER_DEFS_H
 
+#include <etl/list.h>
+
 #include "fsfw/storagemanager/storeAddress.h"
 
 namespace cfdp {