#include #include #include #include #include #include #include typedef int32_t key_serial_t; #ifndef __i386__ #error Sorry, currently only works on i386 #endif #ifndef __NR_add_key #define __NR_add_key 286 #endif /* special process keyring shortcut IDs */ #define KEY_SPEC_THREAD_KEYRING -1 #define KEY_SPEC_PROCESS_KEYRING -2 #define KEY_SPEC_SESSION_KEYRING -3 #define KEY_SPEC_USER_KEYRING -4 #define KEY_SPEC_USER_SESSION_KEYRING -5 #define KEY_SPEC_GROUP_KEYRING -6 static inline key_serial_t add_key(const char *type, const char * description, const void *payload, size_t plen, key_serial_t ringid) { syscall(__NR_add_key, type, description, payload, plen, ringid); } /* * Decode key from its hex representation */ static int crypt_decode_key(uint8_t *key, char *hex, unsigned int size) { char buffer[3]; char *endp; unsigned int i; buffer[2] = '\0'; for(i = 0; i < size; i++) { buffer[0] = *hex++; buffer[1] = *hex++; key[i] = (uint8_t)strtoul(buffer, &endp, 16); if (endp != &buffer[2]) return -EINVAL; } if (*hex != '\0') return -EINVAL; return 0; } int main(int argc, char **argv) { unsigned int key_size; size_t buflen; void *buf, *p; long ret; uint8_t *key = NULL; if (argc != 4) { fprintf(stderr, "Syntax: %s key-name crypto-config hex-key\n", argv[0]); return 1; } key_size = strlen(argv[3]) >> 1; if (key_size > 1024) { fprintf(stderr, "Invalid key size.\n"); return 1; } if (!key_size && strcmp(argv[3], "-") != 0) { fprintf(stderr, "Key invalid.\n"); return 1; } if (key_size) { key = malloc(key_size * sizeof(uint8_t)); if (crypt_decode_key(key, argv[3], key_size) < 0) { fprintf(stderr, "Error decoding key.\n"); return 1; } } buflen = strlen(argv[2]) + 1 + sizeof(uint16_t) + key_size * sizeof(uint8_t); buf = malloc(buflen); strcpy(buf, argv[2]); p = buf + (strlen(buf) + 1); *(uint16_t *)p = key_size; p += sizeof(uint16_t); memcpy(p, key, key_size * sizeof(uint8_t)); free(key); ret = add_key("dm-crypt", argv[1], buf, buflen, KEY_SPEC_USER_KEYRING); free(buf); if (ret < 0) { perror("add_key"); return 1; } printf("new key id: %ld\n", ret); return 0; }