aheinecke@4: #include "listutil.h" aheinecke@4: aheinecke@4: #include aheinecke@4: #include aheinecke@4: #include aheinecke@4: #include aheinecke@4: #include aheinecke@4: #include aheinecke@4: #include aheinecke@7: #include aheinecke@4: aheinecke@28: #ifdef RELEASE aheinecke@28: #include "pubkey-release.h" aheinecke@28: #else aheinecke@28: #include "pubkey-test.h" aheinecke@28: #endif aheinecke@28: aheinecke@28: #pragma GCC diagnostic ignored "-Wconversion" aheinecke@28: /* Polarssl mh.h contains a conversion which gcc warns about */ aheinecke@28: #include aheinecke@28: #pragma GCC diagnostic pop aheinecke@28: aheinecke@4: #define MAX_FILESIZE_KB 1024 aheinecke@4: aheinecke@4: void handle_errno() aheinecke@4: { aheinecke@4: printf("Error: %s \n", strerror(errno)); aheinecke@4: } aheinecke@4: aheinecke@28: list_status_t read_list (const char *file_name, char **data, size_t *size) aheinecke@4: { aheinecke@4: int fd = -1; aheinecke@28: struct stat file_stat; aheinecke@4: int rc = 0; aheinecke@4: ssize_t bRead = 0; aheinecke@7: aheinecke@28: memset(&file_stat, 0, sizeof(file_stat)); aheinecke@7: aheinecke@4: list_status_t retval = UnknownError; aheinecke@4: aheinecke@28: fd = open(file_name, O_RDONLY); aheinecke@4: if (fd == -1) { aheinecke@4: handle_errno(); aheinecke@4: retval = StatFailed; aheinecke@7: goto cleanup; aheinecke@4: } aheinecke@4: aheinecke@28: rc = fstat(fd, &file_stat); aheinecke@4: if (rc < 0) { aheinecke@4: printf ("Stat failed with rc: %i\n", rc); aheinecke@4: retval = StatFailed; aheinecke@7: goto cleanup; aheinecke@4: } aheinecke@4: aheinecke@4: // Check the size of the file aheinecke@28: if (!file_stat.st_size) { aheinecke@4: printf("Size zero\n"); aheinecke@4: retval = StatFailed; aheinecke@7: goto cleanup; aheinecke@4: } aheinecke@4: aheinecke@28: if (file_stat.st_size / 1024 > MAX_FILESIZE_KB && aheinecke@28: file_stat.st_size > 0) { aheinecke@4: printf("File too large\n"); aheinecke@4: retval = TooLarge; aheinecke@7: goto cleanup; aheinecke@4: } aheinecke@4: aheinecke@28: *size = (size_t) file_stat.st_size; aheinecke@4: aheinecke@7: *data = (char*) malloc(*size); aheinecke@4: aheinecke@9: if (*data == NULL) { aheinecke@4: printf("Malloc failed\n"); aheinecke@4: retval = UnknownError; aheinecke@7: goto cleanup; aheinecke@4: } aheinecke@4: aheinecke@7: bRead = read(fd, *data, *size); aheinecke@4: aheinecke@7: if (bRead < 0 || (size_t) bRead != *size) { aheinecke@7: printf("Read failed\n"); aheinecke@4: if (bRead == -1) { aheinecke@4: handle_errno(); aheinecke@4: } aheinecke@4: retval = UnknownError; aheinecke@4: *size = 0; aheinecke@7: if (*data) { aheinecke@7: free(*data); aheinecke@7: printf("Nulling data\n"); aheinecke@7: *data = NULL; aheinecke@4: } aheinecke@7: goto cleanup; aheinecke@4: } aheinecke@4: aheinecke@14: retval = UnknownValidity; aheinecke@7: cleanup: aheinecke@4: aheinecke@4: if (fd && fd != -1) { aheinecke@4: close(fd); aheinecke@4: fd = -1; aheinecke@4: } aheinecke@4: aheinecke@4: return retval; aheinecke@4: } aheinecke@4: aheinecke@28: /** @brief verify the certificate list aheinecke@28: * aheinecke@28: * The public key to verify against is the static publicKeyPEM data defined aheinecke@28: * in the pubkey header. aheinecke@28: * aheinecke@28: * @param [in] data the list data aheinecke@28: * @param [in] size the size of the data aheinecke@28: * aheinecke@28: * @returns 0 if the list is valid a polarssl error or -1 otherwise aheinecke@28: */ aheinecke@28: int verify_list(char *data, size_t size) aheinecke@4: { aheinecke@28: // char *sigstart = data; aheinecke@28: int ret = -1; aheinecke@28: pk_context pub_key_ctx; aheinecke@28: size_t lenpem = strlen((const char*)publicKeyPEM); aheinecke@28: aheinecke@28: pk_init(&pub_key_ctx); aheinecke@28: aheinecke@28: ret = pk_parse_public_key(&pub_key_ctx, publicKeyPEM, lenpem); aheinecke@28: aheinecke@28: if (ret != 0) { aheinecke@28: printf("pk_parse_public_key failed with -0x%04x\n\n", -ret); aheinecke@28: goto done; aheinecke@28: } aheinecke@28: aheinecke@28: done: aheinecke@28: pk_free(&pub_key_ctx); aheinecke@28: return ret; aheinecke@28: } aheinecke@28: aheinecke@28: list_status_t read_and_verify_list(const char *file_name, char **data, aheinecke@28: size_t *size) aheinecke@28: { aheinecke@9: char * signature = NULL; aheinecke@4: aheinecke@4: list_status_t retval = UnknownError; aheinecke@7: *data = NULL; aheinecke@7: *size = 0; aheinecke@4: aheinecke@28: retval = read_list(file_name, data, size); aheinecke@4: aheinecke@14: if (retval != UnknownValidity) { aheinecke@28: printf("Readlist failed\n"); aheinecke@4: return retval; aheinecke@4: } aheinecke@4: aheinecke@7: if (!data || !*size) { aheinecke@28: // should not have happend if read_list works as specified aheinecke@4: return UnknownError; aheinecke@4: } aheinecke@4: aheinecke@9: signature = *data; aheinecke@4: aheinecke@9: if (*signature != 'S') { aheinecke@4: printf("Does not start with S\n"); aheinecke@4: retval = InvalidFormat; aheinecke@7: goto cleanup; aheinecke@4: } aheinecke@4: aheinecke@28: retval = verify_list (*data, *size); aheinecke@9: aheinecke@7: cleanup: aheinecke@7: if (retval != Valid && *data) { aheinecke@7: free(*data); aheinecke@7: *data = NULL; aheinecke@4: *size = 0; aheinecke@4: } aheinecke@4: return retval; aheinecke@4: } aheinecke@4: