I try to use crypto key for decrypting disk in Ubuntu 16 and I want read it from the end of disk just as raw data without creating any file for security reason, i.e. like dd does in way
sudo dd if=some_disk bs=1 skip=end_of_disk - keysize count=keysize
So, I wrote a test program
#include <fcntl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
unsigned long long disksize(char *drivename)
{
int fd;
unsigned long long numblocks=0;
fd = open(drivename, O_RDONLY);
ioctl(fd, BLKGETSIZE64, &numblocks);
close(fd);
return numblocks;
}
int main(int argc, char **argv)
{
int fd;
FILE *device;
int keySize = 2048;
int count;
unsigned char *block;
unsigned long long endOfDisk=disksize(argv[1]);
unsigned long long startFrom = endOfDisk - keySize;
block = calloc(keySize, sizeof(char));
// fd=open(argv[1], O_RDWR | O_DIRECT);
device = fopen(argv[1], "r");
long res = fseek(device, startFrom, SEEK_SET);
perror("\nSeeking error:");
fread(block, 1, keySize, device);
fclose(device);
printf("\nDevice Size: %lld\n", endOfDisk);
printf("\nReading data starting from: %lld\n", startFrom);
for(count = 0; count < keySize; count ){
printf("%c", block[count]);
}
free(block);
}
It works good on small disks, say, on boot partition or USB stick with capacity of 1Gb, but when I try to get key from, say, 4Gb USB stick, I can't: program prints something beyond key area on disk and perror shows "Invalid argument" as result of fseek. It looks like fseek can't set pointer right and I don't understand why:
fdisk -l some_disk
shows exactly the same disk size as endOfDisk from given program.
P.S. As someone can see from a couple of rudiments, I tried lseek too with exactly the same result printing exactly the same info instead of stored on disk key.
CodePudding user response:
ioctl(fd, BLKGETSIZE64, &numblocks)
return size in 512-byte blocks, fseek()
expect offset in bytes.
BTW, you can set pointer relative to the end of disk without knowing it's size:
fseek(device, -keySize, SEEK_END);