Nitrokey / libnitrokey

Communicate with Nitrokey devices in a clean and easy manner
https://nitrokey.com/
GNU Lesser General Public License v3.0
65 stars 34 forks source link

OTP slot names with 15 < length <= 30 are truncated without warning #196

Open robinkrahl opened 3 years ago

robinkrahl commented 3 years ago

The OTP slot name is sent to the device using the SendOTPData command which can store 30 bytes of data. Yet the firmware only stores the first 15 bytes of the slot name.

For slot names with more than 30 bytes, libnitrokey will raise a TooLongStringException in strcpyT called here. For slot names with more than 15 but less than or exactly 30 bytes, libnitrokey will not raise an error and just send the full data to the device which will then truncate the slot name.

In my opinion, libnitrokey should check the slot name length and raise a TooLongStringException if the slot name is too long.

robinkrahl commented 3 years ago

Example code:

#include <stdio.h>
#include <stdlib.h>
#include "../NK_C_API.h"

int main(void)
{
    if (NK_login_auto() != 1) {
        fprintf(stderr, "No Nitrokey device found.\n");
        return 1;
    }

    int result = NK_first_authenticate("12345678", "temppw");
    if (result) {
        fprintf(stderr, "Authentication failed: %x\n", result);
        return 1;
    }

    result = NK_write_totp_slot(0, "12345678901234567890", "deadbeef",
            30, false, false, false, "", "temppw");
    if (result) {
        fprintf(stderr, "Writing OTP slot failed: %x\n", result);
        return 1;
    }

    char *name = NK_get_totp_slot_name(0);
    if (!name) {
        fprintf(stderr, "Querying OTP slot failed: %x\n",
                NK_get_last_command_status());
        return 1;
    }
    printf("Slot name: %s\n", name);
    free(name);

    result = NK_write_totp_slot(0,
            "12345678901234567890123456789012345678901234567890",
            "deadbeef", 30, false, false, false, "", "temppw");
    if (result) {
        fprintf(stderr, "Writing OTP slot failed: %x\n", result);
        return 1;
    }

    NK_logout();
    return 0;
}