diff --git a/src/ate/test_programs/dut_lib/dut_lib.cc b/src/ate/test_programs/dut_lib/dut_lib.cc index d383ad02..f94d5f21 100644 --- a/src/ate/test_programs/dut_lib/dut_lib.cc +++ b/src/ate/test_programs/dut_lib/dut_lib.cc @@ -44,6 +44,8 @@ void OtLibTxCaSerialNums(void* transport, const uint8_t* spi_frame, size_t spi_frame_size, uint64_t timeout_ms); void OtLibRxPersoBlob(void* transport, bool quiet, uint64_t timeout_ms, size_t* num_objects, size_t* next_free, uint8_t* body); +void OtLibTxPersoBlob(void* transport, const uint8_t* spi_frame, + size_t spi_frame_size, uint64_t timeout_ms); } std::unique_ptr DutLib::Create(const std::string& fpga) { @@ -145,5 +147,11 @@ void DutLib::DutRxFtPersoBlob(bool quiet, uint64_t timeout_ms, size_t* num_objs, OtLibRxPersoBlob(transport_, quiet, timeout_ms, num_objs, next_free, body); } +void DutLib::DutTxFtPersoBlob(const uint8_t* spi_frame, size_t spi_frame_size, + uint64_t timeout_ms) { + LOG(INFO) << "in DutLib::DutTxFtPersoBlob"; + OtLibTxPersoBlob(transport_, spi_frame, spi_frame_size, timeout_ms); +} + } // namespace test_programs } // namespace provisioning diff --git a/src/ate/test_programs/dut_lib/dut_lib.h b/src/ate/test_programs/dut_lib/dut_lib.h index 3d817262..8dff4183 100644 --- a/src/ate/test_programs/dut_lib/dut_lib.h +++ b/src/ate/test_programs/dut_lib/dut_lib.h @@ -91,6 +91,12 @@ class DutLib { */ void DutRxFtPersoBlob(bool quiet, uint64_t timeout_ms, size_t* num_objs, size_t* next_free, uint8_t* body); + /** + * Calls opentitanlib methods to send the perso blob back to the DUT, which + * contains the TBS certificates to be endorsed. + */ + void DutTxFtPersoBlob(const uint8_t* spi_frame, size_t spi_frame_size, + uint64_t timeout_ms); private: // Must be 2x the opentitanlib UartConsole buffer size defined here: diff --git a/src/ate/test_programs/ft.cc b/src/ate/test_programs/ft.cc index c8d9f7b6..91e6d89f 100644 --- a/src/ate/test_programs/ft.cc +++ b/src/ate/test_programs/ft.cc @@ -340,7 +340,17 @@ int main(int argc, char **argv) { return -1; } - // TODO(timothytrippel): Send the endorsed certs back to the device. + // Send the endorsed certs back to the device. + perso_blob_t perso_blob_from_ate; + if (PackPersoBlob(num_tbs_certs, endorse_certs_responses, + &perso_blob_from_ate) != 0) { + LOG(ERROR) << "Failed to repack the perso blob."; + return -1; + } + dut->DutTxFtPersoBlob(ca_serial_numbers_spi_frame.payload, + ca_serial_numbers_spi_frame.cursor, + /*timeout_ms=*/1000); + // TODO(timothytrippel): Check the cert chains validate. // TODO(timothytrippel): Register the device. diff --git a/src/ate/test_programs/otlib_wrapper/src/lib.rs b/src/ate/test_programs/otlib_wrapper/src/lib.rs index f582c8a0..d39ccf57 100644 --- a/src/ate/test_programs/otlib_wrapper/src/lib.rs +++ b/src/ate/test_programs/otlib_wrapper/src/lib.rs @@ -706,7 +706,7 @@ pub extern "C" fn OtLibRxPersoBlob( // Receive the UJSON data payload from the DUT over the console. let timeout = Duration::from_millis(timeout_ms); let _ = UartConsole::wait_for(&spi_console, r"Exporting TBS certificates ...", timeout) - .expect("Perso blob device sync message missed."); + .expect("Perso blob device TX sync message missed."); let perso_blob = PersoBlob::recv(&spi_console, timeout, quiet, /*skip_crc=*/ true) .expect("Could not receive perso blob from DUT."); // SAFETY: the size pointers below should be a valid pointers to memory allocated by the caller. @@ -718,3 +718,41 @@ pub extern "C" fn OtLibRxPersoBlob( body[..perso_blob.body.len()].copy_from_slice(perso_blob.body.as_slice()); *next_free = perso_blob.next_free; } + +#[no_mangle] +pub extern "C" fn OtLibTxPersoBlob( + transport: *const TransportWrapper, + spi_frame: *mut u8, + spi_frame_size: usize, + timeout_ms: u64, +) { + // SAFETY: The transport wrapper pointer passed from C side should be the pointer returned by + // the call to `OtLibFpgaTransportInit(...)` above. + let transport: &TransportWrapper = unsafe { &*transport }; + + // SAFETY: spi_frame should be a valid pointer to memory allocated by the caller. + let spi_frame = unsafe { std::slice::from_raw_parts_mut(spi_frame, spi_frame_size) }; + + // Get handle to SPI console. + let spi = transport.spi("BOOTSTRAP").unwrap(); + let device_console_tx_ready_pin = &transport.gpio_pin("IOA5").expect("Unable to get GPIO pin."); + let _ = device_console_tx_ready_pin.set_mode(PinMode::Input); + let _ = device_console_tx_ready_pin.set_pull_mode(PullMode::None); + let spi_console = SpiConsoleDevice::new( + &*spi, + Some(device_console_tx_ready_pin), + /*ignore_frame_num=*/ true, + ) + .expect("Unable to create SPI console."); + + // Send the UJSON data payload to the DUT over the console. + let _ = UartConsole::wait_for( + &spi_console, + r"Importing endorsed certificates ...\n", + Duration::from_millis(timeout_ms), + ) + .expect("Perso blob device RX sync message missed."); + spi_console + .console_write(spi_frame.as_bytes()) + .expect("Unable to write to console."); +}