Revert "Revert "oran-shell-release: release image for F""
[pti/rtp.git] / meta-starlingx / meta-stx-integ / recipes-connectivity / haproxy / haproxy-1.7.11 / haproxy-1.7.11-tpm-support.patch
1 From 2fa8fedba0968d1c6d21d2c7fa33c903f8984815 Mon Sep 17 00:00:00 2001
2 From: Jackie Huang <jackie.huang@windriver.com>
3 Date: Thu, 25 Jul 2019 15:22:49 +0800
4 Subject: [PATCH] haproxy tpm support
5
6 original author: Kam Nasim <kam.nasim@windriver.com>
7
8 rebased for 1.7.11
9
10 Signed-off-by: Jackie Huang <jackie.huang@windriver.com>
11 ---
12  include/types/global.h |  13 +++++
13  src/cfgparse.c         |  28 ++++++++++
14  src/haproxy.c          |  26 ++++++++-
15  src/ssl_sock.c         | 147 +++++++++++++++++++++++++++++++++++++++++++------
16  4 files changed, 197 insertions(+), 17 deletions(-)
17
18 diff --git a/include/types/global.h b/include/types/global.h
19 index 10f3a3c..68f2138 100644
20 --- a/include/types/global.h
21 +++ b/include/types/global.h
22 @@ -37,6 +37,10 @@
23  #include <import/51d.h>
24  #endif
25  
26 +#ifdef USE_OPENSSL
27 +#include <openssl/engine.h>
28 +#endif
29 +
30  #ifndef UNIX_MAX_PATH
31  #define UNIX_MAX_PATH 108
32  #endif
33 @@ -79,6 +83,14 @@ enum {
34         SSL_SERVER_VERIFY_REQUIRED = 1,
35  };
36  
37 +// WRS: Define a new TPM configuration structure
38 +struct tpm_conf {
39 +    char *tpm_object;
40 +    char *tpm_engine;
41 +    EVP_PKEY *tpm_key;
42 +    ENGINE *tpm_engine_ref;
43 +};
44 +
45  /* FIXME : this will have to be redefined correctly */
46  struct global {
47  #ifdef USE_OPENSSL
48 @@ -101,6 +113,7 @@ struct global {
49         char *connect_default_ciphers;
50         int listen_default_ssloptions;
51         int connect_default_ssloptions;
52 +       struct tpm_conf tpm; // tpm configuration
53  #endif
54         unsigned int ssl_server_verify; /* default verify mode on servers side */
55         struct freq_ctr conn_per_sec;
56 diff --git a/src/cfgparse.c b/src/cfgparse.c
57 index 3489f7e..0209874 100644
58 --- a/src/cfgparse.c
59 +++ b/src/cfgparse.c
60 @@ -1923,6 +1923,34 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
61                                 env++;
62                 }
63         }
64 +       else if (!strcmp(args[0], "tpm-object")) {
65 +               if (global.tpm.tpm_object) {
66 +                       free(global.tpm.tpm_object);
67 +               }
68 +#ifdef USE_OPENSSL
69 +               if (*(args[1]) && (access(args[1], F_OK) != -1)) {
70 +                       global.tpm.tpm_object = strdup(args[1]);
71 +               }
72 +#else
73 +               Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
74 +               err_code |= ERR_ALERT | ERR_FATAL;
75 +               goto out;
76 +#endif
77 +    }
78 +       else if (!strcmp(args[0], "tpm-engine")) {
79 +               if (global.tpm.tpm_engine) {
80 +                       free(global.tpm.tpm_engine);
81 +               }
82 +#ifdef USE_OPENSSL
83 +               if (*(args[1]) && (access(args[1], F_OK) != -1)) {
84 +                       global.tpm.tpm_engine = strdup(args[1]);
85 +               }
86 +#else
87 +               Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
88 +               err_code |= ERR_ALERT | ERR_FATAL;
89 +               goto out;
90 +#endif
91 +    }
92         else {
93                 struct cfg_kw_list *kwl;
94                 int index;
95 diff --git a/src/haproxy.c b/src/haproxy.c
96 index f8a0912..f61dacf 100644
97 --- a/src/haproxy.c
98 +++ b/src/haproxy.c
99 @@ -1370,6 +1370,24 @@ static void deinit_stick_rules(struct list *rules)
100         }
101  }
102  
103 +static void deinit_tpm_engine()
104 +{
105 +       /*
106 +     * if the tpm engine is present then
107 +     * deinit it, this is needed to
108 +     * flush the TPM key handle from TPM memory
109 +     */
110 +       if (global.tpm.tpm_engine_ref) {
111 +               ENGINE_finish(global.tpm.tpm_engine_ref);
112 +       }
113 +
114 +       if (global.tpm.tpm_key) {
115 +               EVP_PKEY_free(global.tpm.tpm_key);
116 +       }
117 +       free(global.tpm.tpm_engine);  global.tpm.tpm_engine = NULL;
118 +       free(global.tpm.tpm_object);  global.tpm.tpm_object = NULL;
119 +}
120 +
121  void deinit(void)
122  {
123         struct proxy *p = proxy, *p0;
124 @@ -1646,7 +1664,13 @@ void deinit(void)
125  
126                 free(uap);
127         }
128 -
129 +    
130 +       /* if HAProxy was in TPM mode then deinit
131 +        * that configuration as well.
132 +        */
133 +       if (global.tpm.tpm_object && global.tpm.tpm_object != '\0')
134 +               deinit_tpm_engine();
135 +    
136         userlist_free(userlist);
137  
138         cfg_unregister_sections();
139 diff --git a/src/ssl_sock.c b/src/ssl_sock.c
140 index 87b2584..44d0b48 100644
141 --- a/src/ssl_sock.c
142 +++ b/src/ssl_sock.c
143 @@ -51,6 +51,7 @@
144  #ifndef OPENSSL_NO_DH
145  #include <openssl/dh.h>
146  #endif
147 +#include <openssl/engine.h>
148  
149  #include <import/lru.h>
150  #include <import/xxhash.h>
151 @@ -2360,6 +2361,80 @@ end:
152         return ret;
153  }
154  
155 +/*
156 + * initialize the TPM engine and load the 
157 + * TPM object as private key within the Engine.
158 + * Only do this for the first bind since TPM can
159 + * only load 3-4 contexes before it runs out of memory
160 + */
161 +static int ssl_sock_load_tpm_key(SSL_CTX *ctx, char **err) {
162 +       if (!global.tpm.tpm_object || global.tpm.tpm_object[0] == '\0') {
163 +               /* not in TPM mode */
164 +               return -1;
165 +       }
166 +       if (!global.tpm.tpm_key) {
167 +               Warning ("Could not find tpm_key; initializing engine\n");
168 +               /* no key present; load the dynamic TPM engine */
169 +               if (global.tpm.tpm_engine && global.tpm.tpm_engine[0]) {
170 +                       ENGINE_load_dynamic();
171 +                       ENGINE *engine = ENGINE_by_id("dynamic");
172 +                       if (!engine) {
173 +                               memprintf(err, "%s Unable to load the dynamic engine "
174 +                                         "(needed for loading custom TPM engine)\n",
175 +                                         err && *err ? *err : "");
176 +                               return 1;
177 +            }
178 +
179 +                       ENGINE_ctrl_cmd_string(engine, "SO_PATH", global.tpm.tpm_engine, 0);
180 +                       ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0);
181 +                       /* stow away for ENGINE cleanup */
182 +                       global.tpm.tpm_engine_ref = engine;
183 +
184 +                       if (ENGINE_init(engine) != 1) {
185 +                               const char *error_str = ERR_error_string(ERR_get_error(), NULL); 
186 +                               memprintf(err, "%s Unable to init the TPM engine (%s). Err: %s\n",
187 +                                         err && *err ? *err : "", 
188 +                                         global.tpm.tpm_engine, error_str);
189 +                               goto tpm_err;
190 +                       }
191 +                       EVP_PKEY *pkey = ENGINE_load_private_key(engine, 
192 +                                                                global.tpm.tpm_object,
193 +                                                                NULL, NULL);
194 +                       if (!pkey) {
195 +                               const char *error_str = ERR_error_string(ERR_get_error(), NULL); 
196 +                               memprintf(err, "%s Unable to load TPM object (%s). Err: %s\n",
197 +                                         err && *err ? *err : "", 
198 +                                         global.tpm.tpm_object, error_str);
199 +                               goto tpm_err;
200 +                       }
201 +                       global.tpm.tpm_key = pkey;
202 +               }
203 +               else { /* no TPM engine found */
204 +                       memprintf(err, "%s TPM engine option not set when TPM mode expected\n",
205 +                                 err && *err ? *err : "");
206 +                       goto tpm_err;
207 +               }
208 +       } 
209 +
210 +       if (SSL_CTX_use_PrivateKey(ctx, global.tpm.tpm_key) <= 0){
211 +               const char *error_str = ERR_error_string(ERR_get_error(),
212 +                                                 NULL);
213 +               memprintf(err, "%s Invalid private key provided from TPM engine(%s). Err: %s\n",
214 +                         err && *err ? *err : "", 
215 +                         global.tpm.tpm_object, error_str);
216 +               goto tpm_err;
217 +       }
218 +
219 +       return 0;
220 +
221 +tpm_err:
222 +       ENGINE_finish(global.tpm.tpm_engine_ref);
223 +       global.tpm.tpm_engine_ref = NULL;
224 +       EVP_PKEY_free(global.tpm.tpm_key);
225 +       global.tpm.tpm_key = NULL;
226 +       return 1;
227 +}
228 +
229  static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **sni_filter, int fcount, char **err)
230  {
231         int ret;
232 @@ -2372,26 +2447,54 @@ static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf
233                 return 1;
234         }
235  
236 -       if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
237 -               memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
238 -                         err && *err ? *err : "", path);
239 -               SSL_CTX_free(ctx);
240 -               return 1;
241 +       /* NOTE (knasim-wrs): US93721: TPM support
242 +        * This SSL context applies to SSL frontends only.
243 +        * If the TPM option is set then the Private key 
244 +        * is stored in TPM.
245 +        *
246 +        * Launch the OpenSSL TPM engine and load the TPM
247 +        * Private Key. The Public key will still be located
248 +        * at the provided path and needs to be loaded as
249 +        * per usual.
250 +        */
251 +       if (global.tpm.tpm_object) {
252 +               ret = ssl_sock_load_tpm_key(ctx, err);
253 +               if (ret > 0) {
254 +                       /* tpm configuration failed */
255 +                       SSL_CTX_free(ctx);
256 +                       return 1;
257 +               }
258         }
259 -
260 -       ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
261 -       if (ret <= 0) {
262 -               memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
263 -                         err && *err ? *err : "", path);
264 -               if (ret < 0) /* serious error, must do that ourselves */
265 +       else { /* non TPM mode */
266 +               if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
267 +                       memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
268 +                                 err && *err ? *err : "", path);
269                         SSL_CTX_free(ctx);
270 -               return 1;
271 +                       return 1;
272 +               }
273         }
274  
275 -       if (SSL_CTX_check_private_key(ctx) <= 0) {
276 -               memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
277 -                         err && *err ? *err : "", path);
278 -               return 1;
279 +       ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
280 +               if (ret <= 0) {
281 +                       memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
282 +                                         err && *err ? *err : "", path);
283 +                       if (ret < 0) /* serious error, must do that ourselves */
284 +                               SSL_CTX_free(ctx);
285 +                       return 1;
286 +               }
287 +
288 +       /*
289 +        * only match the private key to the public key
290 +        * for non TPM mode. This op would never work for
291 +        * TPM since the private key has been wrapped, whereas
292 +        * the public key is still the original one.
293 +        */
294 +       if (!global.tpm.tpm_object) {
295 +               if (SSL_CTX_check_private_key(ctx) <= 0) {
296 +                       memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
297 +                                 err && *err ? *err : "", path);
298 +                       return 1;
299 +               }
300         }
301  
302         /* we must not free the SSL_CTX anymore below, since it's already in
303 @@ -3068,6 +3171,18 @@ int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
304                 cfgerr++;
305                 return cfgerr;
306         }
307 +
308 +       /* NOTE (knasim-wrs): US93721: TPM support
309 +        * This SSL context applies to SSL backends only.
310 +        * Since Titanium backends don't support SSL, there
311 +        * is no need to offload these keys in TPM or reuse the
312 +        * same TPM key for the frontend engine. 
313 +        * 
314 +        * If SSL backends are to be supported in the future,
315 +        * over TPM, then create a new TPM Engine context and
316 +        * load the backend key in TPM, in a similar fashion to
317 +        * the frontend key.
318 +        */
319         if (srv->ssl_ctx.client_crt) {
320                 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
321                         Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
322 -- 
323 2.7.4
324