Features/Real rng device
Device Description
"QNG PQ4000KU" is USB hardware device, which is used to generate real random data by hardware. The driver name in linux is fsbi_*
We access the device by libqwqng API, QEMU can read random data from a remote socket(server). So we write a CPP program to read data from device and send the data to remote socket(client).
Install libqwqng (reference QWQNG_Linux.pdf in the provided setup-CD)
- Compile and install the following lib (packages are provided in the setup-CD):
- libusb-1.0
- libFTDI1
- LIBQWQNG-1.3.5
- Update udev rules to change QNG device's permission
- create plugdev group if it doesn't exist
- more detail please reference Section 6 in QWQNG_Linux.pdf
# cp ~/libqwqng-1.3.5/packages/45-libqwqng.rules /etc/udev/rules.d/ # udevadm control --reload-rules # groupadd plugdev # usermod -G plugdev -a USER
- Compile and execute test examples to verify libQWQNG works
host) # cd libqwqng-1.3.5/examples/ host) # make host) # ./randbytes
Expected result: can read 10 bytes data, which will be converted to hex format.
About socket interface
UDP socket chardev is just a data channel. If qemu set a connect UDP socket(client), you should create a listen UDP socket(server), and write the random data to remote socket when client connects the server.
If qemu set a listen UDP socket, you should create a connect UDP socket, and try to connect the server socket, and write data to remote socket.
It's same with TCP socket, or unix socket.
Read data from dev by QWQNG API
Write a CPP program, add it to "libqwqng-1.3.5/examples/" for compiling
char* randbyte; int bytecount = 10; QNG = new QWQNG(); QNG->RandBytes(randbyte, bytecount)) delete [] randbyte; delete QNG;
Write data to the remote socket
int sock_fd, accept_sock; struct sockaddr_in server_addr; server_addr.sin_family=AF_INET; server_addr.sin_port=htons(1024); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); sock_fd = socket(PF_INET, SOCK_STREAM, 0); bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr); listen(sock_fd,4); accept_sock = accept(sock_fd, NULL, NULL); while (1) send(accept_sock, randbyte, sizeof(randbyte), 0);
The whole CPP program: VirtRng-RandBytes.cpp
host) # cp libqwqng-1.3.5/examples/RandBytes.cpp libqwqng-1.3.5/examples/RandBytes.cpp.bak host) # cp RandBytes.cpp libqwqng-1.3.5/examples/ host) # cd libqwqng-1.3.5/examples/ host) # make host) # ./randbytes
Launch qemu with the virtio-rng backend of socket rng-egd
# qemu-kvm -vnc :0 -snapshot /images/RHEL-Server-6.4-64-virtio.qcow2 \ -monitor stdio --enable-kvm -m 2000 \ -chardev socket,host=10.66.4.212,port=1024,id=chr0 \ -object rng-egd,chardev=chr0,id=rng0 \ -device virtio-rng-pci,rng=rng0
note: 10.66.4.212 is the IP address of the host that is executing "./randbytes"
Guest can read random data from /dev/hwrng
guest) # dd if=/dev/hwrng of=/dev/stdout
Expected result: randome data is outputted to the terminal.