1 /*
2 * Copyright (C) 2014-2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* Trusty Random Number Generation library.
18 * Provides a CSPRNG and an interface to a HWRNG if present. The functions
19 * in this library are currently not threadsafe. It is designed to be used
20 * from a single-threaded Trusty application.
21 */
22
23 #include <lib/rng/trusty_rng.h>
24
25 #include <stdbool.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <trusty_ipc.h>
29 #include <uapi/err.h>
30
31 #include <interface/hwrng/hwrng.h>
32 #include <openssl/rand.h>
33
34 /*
35 * This is the generic part of the trusty app rng service.
36 * A server implementation for retrieving hardware backed
37 * random numbers, used by trusty_rng_hw_rand,
38 * is required to be provided by a hardware
39 * specific backend at tipc port HWRNG_PORT.
40 *
41 * Clients of this library are encouraged to use the
42 * trusty_rng_secure_rand rather than the trusty_rng_hw_rand
43 * routine, as the latter incurs an IPC penalty with connection
44 * overhead.
45 */
46
trusty_rng_secure_rand(uint8_t * data,size_t len)47 int trusty_rng_secure_rand(uint8_t* data, size_t len) {
48 if (!data || !len)
49 return ERR_INVALID_ARGS;
50
51 int ssl_err = RAND_bytes(data, len);
52 if (ssl_err != 1) {
53 /*
54 * BoringSSL never returns anything but success, so we should never hit
55 * this.
56 */
57 return ERR_GENERIC;
58 }
59
60 return NO_ERROR;
61 }
62
trusty_rng_add_entropy(const uint8_t * data,size_t len)63 int trusty_rng_add_entropy(const uint8_t* data, size_t len) {
64 /*
65 * We now use BoringSSL's PRNG, so this function does not do anything.
66 */
67 return NO_ERROR;
68 }
69
trusty_rng_hw_rand(uint8_t * data,size_t len)70 __WEAK int trusty_rng_hw_rand(uint8_t* data, size_t len) {
71 struct hwrng_req req_hdr = {.len = len};
72
73 struct iovec tx_iov = {
74 .iov_base = &req_hdr,
75 .iov_len = sizeof(req_hdr),
76 };
77
78 ipc_msg_t tx_msg = {
79 .iov = &tx_iov,
80 .num_iov = 1,
81 };
82
83 struct iovec rx_iov = {
84 .iov_base = data,
85 .iov_len = len,
86 };
87 ipc_msg_t rx_msg = {
88 .iov = &rx_iov,
89 .num_iov = 1,
90 };
91
92 long rc = connect(HWRNG_PORT, IPC_CONNECT_WAIT_FOR_PORT);
93 if (rc < 0) {
94 return rc;
95 }
96
97 handle_t chan = (handle_t)rc;
98
99 rc = send_msg(chan, &tx_msg);
100 if (rc < 0) {
101 goto err;
102 }
103
104 if (rc != sizeof(req_hdr)) {
105 rc = ERR_IO;
106 goto err;
107 }
108
109 while (rx_msg.iov[0].iov_len > 0) {
110 uevent_t uevt;
111 rc = wait(chan, &uevt, INFINITE_TIME);
112 if (rc != NO_ERROR) {
113 goto err;
114 }
115
116 ipc_msg_info_t inf;
117 rc = get_msg(chan, &inf);
118 if (rc != NO_ERROR) {
119 goto err;
120 }
121
122 if (inf.len > rx_msg.iov[0].iov_len) {
123 // received too much data
124 rc = ERR_BAD_LEN;
125 goto err;
126 }
127
128 rc = read_msg(chan, inf.id, 0, &rx_msg);
129 if (rc < 0) {
130 goto err;
131 }
132
133 size_t rx_size = (size_t)rc;
134 rx_msg.iov[0].iov_base += rx_size;
135 rx_msg.iov[0].iov_len -= rx_size;
136 put_msg(chan, inf.id);
137 }
138
139 rc = NO_ERROR;
140 err:
141 close(chan);
142 return rc;
143 }
144