• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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