1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery */
9*e7be843bSPierre Pronchery
10*e7be843bSPierre Pronchery #include <stdio.h>
11*e7be843bSPierre Pronchery #include "ssl_local.h"
12*e7be843bSPierre Pronchery #include "internal/e_os.h"
13*e7be843bSPierre Pronchery #include "internal/refcount.h"
14*e7be843bSPierre Pronchery #include "internal/ssl_unwrap.h"
15*e7be843bSPierre Pronchery
ossl_calculate_comp_expansion(int alg,size_t length)16*e7be843bSPierre Pronchery size_t ossl_calculate_comp_expansion(int alg, size_t length)
17*e7be843bSPierre Pronchery {
18*e7be843bSPierre Pronchery size_t ret;
19*e7be843bSPierre Pronchery /*
20*e7be843bSPierre Pronchery * Uncompressibility expansion:
21*e7be843bSPierre Pronchery * ZLIB: N + 11 + 5 * (N >> 14)
22*e7be843bSPierre Pronchery * Brotli: per RFC7932: N + 5 + 3 * (N >> 16)
23*e7be843bSPierre Pronchery * ZSTD: N + 4 + 14 + 3 * (N >> 17) + 4
24*e7be843bSPierre Pronchery */
25*e7be843bSPierre Pronchery
26*e7be843bSPierre Pronchery switch (alg) {
27*e7be843bSPierre Pronchery case TLSEXT_comp_cert_zlib:
28*e7be843bSPierre Pronchery ret = length + 11 + 5 * (length >> 14);
29*e7be843bSPierre Pronchery break;
30*e7be843bSPierre Pronchery case TLSEXT_comp_cert_brotli:
31*e7be843bSPierre Pronchery ret = length + 5 + 3 * (length >> 16);
32*e7be843bSPierre Pronchery break;
33*e7be843bSPierre Pronchery case TLSEXT_comp_cert_zstd:
34*e7be843bSPierre Pronchery ret = length + 22 + 3 * (length >> 17);
35*e7be843bSPierre Pronchery break;
36*e7be843bSPierre Pronchery default:
37*e7be843bSPierre Pronchery return 0;
38*e7be843bSPierre Pronchery }
39*e7be843bSPierre Pronchery /* Check for overflow */
40*e7be843bSPierre Pronchery if (ret < length)
41*e7be843bSPierre Pronchery return 0;
42*e7be843bSPierre Pronchery return ret;
43*e7be843bSPierre Pronchery }
44*e7be843bSPierre Pronchery
ossl_comp_has_alg(int a)45*e7be843bSPierre Pronchery int ossl_comp_has_alg(int a)
46*e7be843bSPierre Pronchery {
47*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
48*e7be843bSPierre Pronchery /* 0 means "any" algorithm */
49*e7be843bSPierre Pronchery if ((a == 0 || a == TLSEXT_comp_cert_brotli) && BIO_f_brotli() != NULL)
50*e7be843bSPierre Pronchery return 1;
51*e7be843bSPierre Pronchery if ((a == 0 || a == TLSEXT_comp_cert_zstd) && BIO_f_zstd() != NULL)
52*e7be843bSPierre Pronchery return 1;
53*e7be843bSPierre Pronchery if ((a == 0 || a == TLSEXT_comp_cert_zlib) && BIO_f_zlib() != NULL)
54*e7be843bSPierre Pronchery return 1;
55*e7be843bSPierre Pronchery #endif
56*e7be843bSPierre Pronchery return 0;
57*e7be843bSPierre Pronchery }
58*e7be843bSPierre Pronchery
59*e7be843bSPierre Pronchery /* New operation Helper routine */
60*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
OSSL_COMP_CERT_new(unsigned char * data,size_t len,size_t orig_len,int alg)61*e7be843bSPierre Pronchery static OSSL_COMP_CERT *OSSL_COMP_CERT_new(unsigned char *data, size_t len, size_t orig_len, int alg)
62*e7be843bSPierre Pronchery {
63*e7be843bSPierre Pronchery OSSL_COMP_CERT *ret = NULL;
64*e7be843bSPierre Pronchery
65*e7be843bSPierre Pronchery if (!ossl_comp_has_alg(alg)
66*e7be843bSPierre Pronchery || data == NULL
67*e7be843bSPierre Pronchery || (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL
68*e7be843bSPierre Pronchery || !CRYPTO_NEW_REF(&ret->references, 1))
69*e7be843bSPierre Pronchery goto err;
70*e7be843bSPierre Pronchery
71*e7be843bSPierre Pronchery ret->data = data;
72*e7be843bSPierre Pronchery ret->len = len;
73*e7be843bSPierre Pronchery ret->orig_len = orig_len;
74*e7be843bSPierre Pronchery ret->alg = alg;
75*e7be843bSPierre Pronchery return ret;
76*e7be843bSPierre Pronchery err:
77*e7be843bSPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
78*e7be843bSPierre Pronchery OPENSSL_free(data);
79*e7be843bSPierre Pronchery OPENSSL_free(ret);
80*e7be843bSPierre Pronchery return NULL;
81*e7be843bSPierre Pronchery }
82*e7be843bSPierre Pronchery
OSSL_COMP_CERT_from_compressed_data(unsigned char * data,size_t len,size_t orig_len,int alg)83*e7be843bSPierre Pronchery __owur static OSSL_COMP_CERT *OSSL_COMP_CERT_from_compressed_data(unsigned char *data, size_t len,
84*e7be843bSPierre Pronchery size_t orig_len, int alg)
85*e7be843bSPierre Pronchery {
86*e7be843bSPierre Pronchery return OSSL_COMP_CERT_new(OPENSSL_memdup(data, len), len, orig_len, alg);
87*e7be843bSPierre Pronchery }
88*e7be843bSPierre Pronchery
OSSL_COMP_CERT_from_uncompressed_data(unsigned char * data,size_t len,int alg)89*e7be843bSPierre Pronchery __owur static OSSL_COMP_CERT *OSSL_COMP_CERT_from_uncompressed_data(unsigned char *data, size_t len,
90*e7be843bSPierre Pronchery int alg)
91*e7be843bSPierre Pronchery {
92*e7be843bSPierre Pronchery OSSL_COMP_CERT *ret = NULL;
93*e7be843bSPierre Pronchery size_t max_length;
94*e7be843bSPierre Pronchery int comp_length;
95*e7be843bSPierre Pronchery COMP_METHOD *method;
96*e7be843bSPierre Pronchery unsigned char *comp_data = NULL;
97*e7be843bSPierre Pronchery COMP_CTX *comp_ctx = NULL;
98*e7be843bSPierre Pronchery
99*e7be843bSPierre Pronchery switch (alg) {
100*e7be843bSPierre Pronchery case TLSEXT_comp_cert_brotli:
101*e7be843bSPierre Pronchery method = COMP_brotli_oneshot();
102*e7be843bSPierre Pronchery break;
103*e7be843bSPierre Pronchery case TLSEXT_comp_cert_zlib:
104*e7be843bSPierre Pronchery method = COMP_zlib_oneshot();
105*e7be843bSPierre Pronchery break;
106*e7be843bSPierre Pronchery case TLSEXT_comp_cert_zstd:
107*e7be843bSPierre Pronchery method = COMP_zstd_oneshot();
108*e7be843bSPierre Pronchery break;
109*e7be843bSPierre Pronchery default:
110*e7be843bSPierre Pronchery goto err;
111*e7be843bSPierre Pronchery }
112*e7be843bSPierre Pronchery
113*e7be843bSPierre Pronchery if ((max_length = ossl_calculate_comp_expansion(alg, len)) == 0
114*e7be843bSPierre Pronchery || method == NULL
115*e7be843bSPierre Pronchery || (comp_ctx = COMP_CTX_new(method)) == NULL
116*e7be843bSPierre Pronchery || (comp_data = OPENSSL_zalloc(max_length)) == NULL)
117*e7be843bSPierre Pronchery goto err;
118*e7be843bSPierre Pronchery
119*e7be843bSPierre Pronchery comp_length = COMP_compress_block(comp_ctx, comp_data, max_length, data, len);
120*e7be843bSPierre Pronchery if (comp_length <= 0)
121*e7be843bSPierre Pronchery goto err;
122*e7be843bSPierre Pronchery
123*e7be843bSPierre Pronchery ret = OSSL_COMP_CERT_new(comp_data, comp_length, len, alg);
124*e7be843bSPierre Pronchery comp_data = NULL;
125*e7be843bSPierre Pronchery
126*e7be843bSPierre Pronchery err:
127*e7be843bSPierre Pronchery OPENSSL_free(comp_data);
128*e7be843bSPierre Pronchery COMP_CTX_free(comp_ctx);
129*e7be843bSPierre Pronchery return ret;
130*e7be843bSPierre Pronchery }
131*e7be843bSPierre Pronchery
OSSL_COMP_CERT_free(OSSL_COMP_CERT * cc)132*e7be843bSPierre Pronchery void OSSL_COMP_CERT_free(OSSL_COMP_CERT *cc)
133*e7be843bSPierre Pronchery {
134*e7be843bSPierre Pronchery int i;
135*e7be843bSPierre Pronchery
136*e7be843bSPierre Pronchery if (cc == NULL)
137*e7be843bSPierre Pronchery return;
138*e7be843bSPierre Pronchery
139*e7be843bSPierre Pronchery CRYPTO_DOWN_REF(&cc->references, &i);
140*e7be843bSPierre Pronchery REF_PRINT_COUNT("OSSL_COMP_CERT", i, cc);
141*e7be843bSPierre Pronchery if (i > 0)
142*e7be843bSPierre Pronchery return;
143*e7be843bSPierre Pronchery REF_ASSERT_ISNT(i < 0);
144*e7be843bSPierre Pronchery
145*e7be843bSPierre Pronchery OPENSSL_free(cc->data);
146*e7be843bSPierre Pronchery CRYPTO_FREE_REF(&cc->references);
147*e7be843bSPierre Pronchery OPENSSL_free(cc);
148*e7be843bSPierre Pronchery }
OSSL_COMP_CERT_up_ref(OSSL_COMP_CERT * cc)149*e7be843bSPierre Pronchery int OSSL_COMP_CERT_up_ref(OSSL_COMP_CERT *cc)
150*e7be843bSPierre Pronchery {
151*e7be843bSPierre Pronchery int i;
152*e7be843bSPierre Pronchery
153*e7be843bSPierre Pronchery if (CRYPTO_UP_REF(&cc->references, &i) <= 0)
154*e7be843bSPierre Pronchery return 0;
155*e7be843bSPierre Pronchery
156*e7be843bSPierre Pronchery REF_PRINT_COUNT("OSSL_COMP_CERT", i, cc);
157*e7be843bSPierre Pronchery REF_ASSERT_ISNT(i < 2);
158*e7be843bSPierre Pronchery return ((i > 1) ? 1 : 0);
159*e7be843bSPierre Pronchery }
160*e7be843bSPierre Pronchery
ssl_set_cert_comp_pref(int * prefs,int * algs,size_t len)161*e7be843bSPierre Pronchery static int ssl_set_cert_comp_pref(int *prefs, int *algs, size_t len)
162*e7be843bSPierre Pronchery {
163*e7be843bSPierre Pronchery size_t j = 0;
164*e7be843bSPierre Pronchery size_t i;
165*e7be843bSPierre Pronchery int found = 0;
166*e7be843bSPierre Pronchery int already_set[TLSEXT_comp_cert_limit];
167*e7be843bSPierre Pronchery int tmp_prefs[TLSEXT_comp_cert_limit];
168*e7be843bSPierre Pronchery
169*e7be843bSPierre Pronchery /* Note that |len| is the number of |algs| elements */
170*e7be843bSPierre Pronchery /* clear all algorithms */
171*e7be843bSPierre Pronchery if (len == 0 || algs == NULL) {
172*e7be843bSPierre Pronchery memset(prefs, 0, sizeof(tmp_prefs));
173*e7be843bSPierre Pronchery return 1;
174*e7be843bSPierre Pronchery }
175*e7be843bSPierre Pronchery
176*e7be843bSPierre Pronchery /* This will 0-terminate the array */
177*e7be843bSPierre Pronchery memset(tmp_prefs, 0, sizeof(tmp_prefs));
178*e7be843bSPierre Pronchery memset(already_set, 0, sizeof(already_set));
179*e7be843bSPierre Pronchery /* Include only those algorithms we support, ignoring duplicates and unknowns */
180*e7be843bSPierre Pronchery for (i = 0; i < len; i++) {
181*e7be843bSPierre Pronchery if (algs[i] != 0 && ossl_comp_has_alg(algs[i])) {
182*e7be843bSPierre Pronchery /* Check for duplicate */
183*e7be843bSPierre Pronchery if (already_set[algs[i]])
184*e7be843bSPierre Pronchery return 0;
185*e7be843bSPierre Pronchery tmp_prefs[j++] = algs[i];
186*e7be843bSPierre Pronchery already_set[algs[i]] = 1;
187*e7be843bSPierre Pronchery found = 1;
188*e7be843bSPierre Pronchery }
189*e7be843bSPierre Pronchery }
190*e7be843bSPierre Pronchery if (found)
191*e7be843bSPierre Pronchery memcpy(prefs, tmp_prefs, sizeof(tmp_prefs));
192*e7be843bSPierre Pronchery return found;
193*e7be843bSPierre Pronchery }
194*e7be843bSPierre Pronchery
ssl_get_cert_to_compress(SSL * ssl,CERT_PKEY * cpk,unsigned char ** data)195*e7be843bSPierre Pronchery static size_t ssl_get_cert_to_compress(SSL *ssl, CERT_PKEY *cpk, unsigned char **data)
196*e7be843bSPierre Pronchery {
197*e7be843bSPierre Pronchery SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
198*e7be843bSPierre Pronchery WPACKET tmppkt;
199*e7be843bSPierre Pronchery BUF_MEM buf = { 0 };
200*e7be843bSPierre Pronchery size_t ret = 0;
201*e7be843bSPierre Pronchery
202*e7be843bSPierre Pronchery if (sc == NULL
203*e7be843bSPierre Pronchery || cpk == NULL
204*e7be843bSPierre Pronchery || !sc->server
205*e7be843bSPierre Pronchery || !SSL_in_before(ssl))
206*e7be843bSPierre Pronchery return 0;
207*e7be843bSPierre Pronchery
208*e7be843bSPierre Pronchery /* Use the |tmppkt| for the to-be-compressed data */
209*e7be843bSPierre Pronchery if (!WPACKET_init(&tmppkt, &buf))
210*e7be843bSPierre Pronchery goto out;
211*e7be843bSPierre Pronchery
212*e7be843bSPierre Pronchery /* no context present, add 0-length context */
213*e7be843bSPierre Pronchery if (!WPACKET_put_bytes_u8(&tmppkt, 0))
214*e7be843bSPierre Pronchery goto out;
215*e7be843bSPierre Pronchery
216*e7be843bSPierre Pronchery /*
217*e7be843bSPierre Pronchery * ssl3_output_cert_chain() may generate an SSLfatal() error,
218*e7be843bSPierre Pronchery * for this case, we want to ignore it, argument for_comp = 1
219*e7be843bSPierre Pronchery */
220*e7be843bSPierre Pronchery if (!ssl3_output_cert_chain(sc, &tmppkt, cpk, 1))
221*e7be843bSPierre Pronchery goto out;
222*e7be843bSPierre Pronchery WPACKET_get_total_written(&tmppkt, &ret);
223*e7be843bSPierre Pronchery
224*e7be843bSPierre Pronchery out:
225*e7be843bSPierre Pronchery WPACKET_cleanup(&tmppkt);
226*e7be843bSPierre Pronchery if (ret != 0 && data != NULL)
227*e7be843bSPierre Pronchery *data = (unsigned char *)buf.data;
228*e7be843bSPierre Pronchery else
229*e7be843bSPierre Pronchery OPENSSL_free(buf.data);
230*e7be843bSPierre Pronchery return ret;
231*e7be843bSPierre Pronchery }
232*e7be843bSPierre Pronchery
ssl_compress_one_cert(SSL * ssl,CERT_PKEY * cpk,int alg)233*e7be843bSPierre Pronchery static int ssl_compress_one_cert(SSL *ssl, CERT_PKEY *cpk, int alg)
234*e7be843bSPierre Pronchery {
235*e7be843bSPierre Pronchery unsigned char *cert_data = NULL;
236*e7be843bSPierre Pronchery OSSL_COMP_CERT *comp_cert = NULL;
237*e7be843bSPierre Pronchery size_t length;
238*e7be843bSPierre Pronchery
239*e7be843bSPierre Pronchery if (cpk == NULL
240*e7be843bSPierre Pronchery || alg == TLSEXT_comp_cert_none
241*e7be843bSPierre Pronchery || !ossl_comp_has_alg(alg))
242*e7be843bSPierre Pronchery return 0;
243*e7be843bSPierre Pronchery
244*e7be843bSPierre Pronchery if ((length = ssl_get_cert_to_compress(ssl, cpk, &cert_data)) == 0)
245*e7be843bSPierre Pronchery return 0;
246*e7be843bSPierre Pronchery comp_cert = OSSL_COMP_CERT_from_uncompressed_data(cert_data, length, alg);
247*e7be843bSPierre Pronchery OPENSSL_free(cert_data);
248*e7be843bSPierre Pronchery if (comp_cert == NULL)
249*e7be843bSPierre Pronchery return 0;
250*e7be843bSPierre Pronchery
251*e7be843bSPierre Pronchery OSSL_COMP_CERT_free(cpk->comp_cert[alg]);
252*e7be843bSPierre Pronchery cpk->comp_cert[alg] = comp_cert;
253*e7be843bSPierre Pronchery return 1;
254*e7be843bSPierre Pronchery }
255*e7be843bSPierre Pronchery
256*e7be843bSPierre Pronchery /* alg_in can be 0, meaning any/all algorithms */
ssl_compress_certs(SSL * ssl,CERT_PKEY * cpks,int alg_in)257*e7be843bSPierre Pronchery static int ssl_compress_certs(SSL *ssl, CERT_PKEY *cpks, int alg_in)
258*e7be843bSPierre Pronchery {
259*e7be843bSPierre Pronchery SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
260*e7be843bSPierre Pronchery int i;
261*e7be843bSPierre Pronchery int j;
262*e7be843bSPierre Pronchery int alg;
263*e7be843bSPierre Pronchery int count = 0;
264*e7be843bSPierre Pronchery
265*e7be843bSPierre Pronchery if (sc == NULL
266*e7be843bSPierre Pronchery || cpks == NULL
267*e7be843bSPierre Pronchery || !ossl_comp_has_alg(alg_in))
268*e7be843bSPierre Pronchery return 0;
269*e7be843bSPierre Pronchery
270*e7be843bSPierre Pronchery /* Look through the preferences to see what we have */
271*e7be843bSPierre Pronchery for (i = 0; i < TLSEXT_comp_cert_limit; i++) {
272*e7be843bSPierre Pronchery /*
273*e7be843bSPierre Pronchery * alg = 0 means compress for everything, but only for algorithms enabled
274*e7be843bSPierre Pronchery * alg != 0 means compress for that algorithm if enabled
275*e7be843bSPierre Pronchery */
276*e7be843bSPierre Pronchery alg = sc->cert_comp_prefs[i];
277*e7be843bSPierre Pronchery if ((alg_in == 0 && alg != TLSEXT_comp_cert_none)
278*e7be843bSPierre Pronchery || (alg_in != 0 && alg == alg_in)) {
279*e7be843bSPierre Pronchery
280*e7be843bSPierre Pronchery for (j = 0; j < SSL_PKEY_NUM; j++) {
281*e7be843bSPierre Pronchery /* No cert, move on */
282*e7be843bSPierre Pronchery if (cpks[j].x509 == NULL)
283*e7be843bSPierre Pronchery continue;
284*e7be843bSPierre Pronchery
285*e7be843bSPierre Pronchery if (!ssl_compress_one_cert(ssl, &cpks[j], alg))
286*e7be843bSPierre Pronchery return 0;
287*e7be843bSPierre Pronchery
288*e7be843bSPierre Pronchery /* if the cert expanded, set the value in the CERT_PKEY to NULL */
289*e7be843bSPierre Pronchery if (cpks[j].comp_cert[alg]->len >= cpks[j].comp_cert[alg]->orig_len) {
290*e7be843bSPierre Pronchery OSSL_COMP_CERT_free(cpks[j].comp_cert[alg]);
291*e7be843bSPierre Pronchery cpks[j].comp_cert[alg] = NULL;
292*e7be843bSPierre Pronchery } else {
293*e7be843bSPierre Pronchery count++;
294*e7be843bSPierre Pronchery }
295*e7be843bSPierre Pronchery }
296*e7be843bSPierre Pronchery }
297*e7be843bSPierre Pronchery }
298*e7be843bSPierre Pronchery return (count > 0);
299*e7be843bSPierre Pronchery }
300*e7be843bSPierre Pronchery
ssl_get_compressed_cert(SSL * ssl,CERT_PKEY * cpk,int alg,unsigned char ** data,size_t * orig_len)301*e7be843bSPierre Pronchery static size_t ssl_get_compressed_cert(SSL *ssl, CERT_PKEY *cpk, int alg, unsigned char **data,
302*e7be843bSPierre Pronchery size_t *orig_len)
303*e7be843bSPierre Pronchery {
304*e7be843bSPierre Pronchery SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
305*e7be843bSPierre Pronchery size_t cert_len = 0;
306*e7be843bSPierre Pronchery size_t comp_len = 0;
307*e7be843bSPierre Pronchery unsigned char *cert_data = NULL;
308*e7be843bSPierre Pronchery OSSL_COMP_CERT *comp_cert = NULL;
309*e7be843bSPierre Pronchery
310*e7be843bSPierre Pronchery if (sc == NULL
311*e7be843bSPierre Pronchery || cpk == NULL
312*e7be843bSPierre Pronchery || data == NULL
313*e7be843bSPierre Pronchery || orig_len == NULL
314*e7be843bSPierre Pronchery || !sc->server
315*e7be843bSPierre Pronchery || !SSL_in_before(ssl)
316*e7be843bSPierre Pronchery || !ossl_comp_has_alg(alg))
317*e7be843bSPierre Pronchery return 0;
318*e7be843bSPierre Pronchery
319*e7be843bSPierre Pronchery if ((cert_len = ssl_get_cert_to_compress(ssl, cpk, &cert_data)) == 0)
320*e7be843bSPierre Pronchery goto err;
321*e7be843bSPierre Pronchery
322*e7be843bSPierre Pronchery comp_cert = OSSL_COMP_CERT_from_uncompressed_data(cert_data, cert_len, alg);
323*e7be843bSPierre Pronchery OPENSSL_free(cert_data);
324*e7be843bSPierre Pronchery if (comp_cert == NULL)
325*e7be843bSPierre Pronchery goto err;
326*e7be843bSPierre Pronchery
327*e7be843bSPierre Pronchery comp_len = comp_cert->len;
328*e7be843bSPierre Pronchery *orig_len = comp_cert->orig_len;
329*e7be843bSPierre Pronchery *data = comp_cert->data;
330*e7be843bSPierre Pronchery comp_cert->data = NULL;
331*e7be843bSPierre Pronchery err:
332*e7be843bSPierre Pronchery OSSL_COMP_CERT_free(comp_cert);
333*e7be843bSPierre Pronchery return comp_len;
334*e7be843bSPierre Pronchery }
335*e7be843bSPierre Pronchery
ossl_set1_compressed_cert(CERT * cert,int algorithm,unsigned char * comp_data,size_t comp_length,size_t orig_length)336*e7be843bSPierre Pronchery static int ossl_set1_compressed_cert(CERT *cert, int algorithm,
337*e7be843bSPierre Pronchery unsigned char *comp_data, size_t comp_length,
338*e7be843bSPierre Pronchery size_t orig_length)
339*e7be843bSPierre Pronchery {
340*e7be843bSPierre Pronchery OSSL_COMP_CERT *comp_cert;
341*e7be843bSPierre Pronchery
342*e7be843bSPierre Pronchery /* No explicit cert set */
343*e7be843bSPierre Pronchery if (cert == NULL || cert->key == NULL)
344*e7be843bSPierre Pronchery return 0;
345*e7be843bSPierre Pronchery
346*e7be843bSPierre Pronchery comp_cert = OSSL_COMP_CERT_from_compressed_data(comp_data, comp_length,
347*e7be843bSPierre Pronchery orig_length, algorithm);
348*e7be843bSPierre Pronchery if (comp_cert == NULL)
349*e7be843bSPierre Pronchery return 0;
350*e7be843bSPierre Pronchery
351*e7be843bSPierre Pronchery OSSL_COMP_CERT_free(cert->key->comp_cert[algorithm]);
352*e7be843bSPierre Pronchery cert->key->comp_cert[algorithm] = comp_cert;
353*e7be843bSPierre Pronchery
354*e7be843bSPierre Pronchery return 1;
355*e7be843bSPierre Pronchery }
356*e7be843bSPierre Pronchery #endif
357*e7be843bSPierre Pronchery
358*e7be843bSPierre Pronchery /*-
359*e7be843bSPierre Pronchery * Public API
360*e7be843bSPierre Pronchery */
SSL_CTX_set1_cert_comp_preference(SSL_CTX * ctx,int * algs,size_t len)361*e7be843bSPierre Pronchery int SSL_CTX_set1_cert_comp_preference(SSL_CTX *ctx, int *algs, size_t len)
362*e7be843bSPierre Pronchery {
363*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
364*e7be843bSPierre Pronchery return ssl_set_cert_comp_pref(ctx->cert_comp_prefs, algs, len);
365*e7be843bSPierre Pronchery #else
366*e7be843bSPierre Pronchery return 0;
367*e7be843bSPierre Pronchery #endif
368*e7be843bSPierre Pronchery }
369*e7be843bSPierre Pronchery
SSL_set1_cert_comp_preference(SSL * ssl,int * algs,size_t len)370*e7be843bSPierre Pronchery int SSL_set1_cert_comp_preference(SSL *ssl, int *algs, size_t len)
371*e7be843bSPierre Pronchery {
372*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
373*e7be843bSPierre Pronchery SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
374*e7be843bSPierre Pronchery
375*e7be843bSPierre Pronchery if (sc == NULL)
376*e7be843bSPierre Pronchery return 0;
377*e7be843bSPierre Pronchery return ssl_set_cert_comp_pref(sc->cert_comp_prefs, algs, len);
378*e7be843bSPierre Pronchery #else
379*e7be843bSPierre Pronchery return 0;
380*e7be843bSPierre Pronchery #endif
381*e7be843bSPierre Pronchery }
382*e7be843bSPierre Pronchery
SSL_compress_certs(SSL * ssl,int alg)383*e7be843bSPierre Pronchery int SSL_compress_certs(SSL *ssl, int alg)
384*e7be843bSPierre Pronchery {
385*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
386*e7be843bSPierre Pronchery SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
387*e7be843bSPierre Pronchery
388*e7be843bSPierre Pronchery if (sc == NULL || sc->cert == NULL)
389*e7be843bSPierre Pronchery return 0;
390*e7be843bSPierre Pronchery
391*e7be843bSPierre Pronchery return ssl_compress_certs(ssl, sc->cert->pkeys, alg);
392*e7be843bSPierre Pronchery #endif
393*e7be843bSPierre Pronchery return 0;
394*e7be843bSPierre Pronchery }
395*e7be843bSPierre Pronchery
SSL_CTX_compress_certs(SSL_CTX * ctx,int alg)396*e7be843bSPierre Pronchery int SSL_CTX_compress_certs(SSL_CTX *ctx, int alg)
397*e7be843bSPierre Pronchery {
398*e7be843bSPierre Pronchery int ret = 0;
399*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
400*e7be843bSPierre Pronchery SSL *new = SSL_new(ctx);
401*e7be843bSPierre Pronchery
402*e7be843bSPierre Pronchery if (new == NULL)
403*e7be843bSPierre Pronchery return 0;
404*e7be843bSPierre Pronchery
405*e7be843bSPierre Pronchery ret = ssl_compress_certs(new, ctx->cert->pkeys, alg);
406*e7be843bSPierre Pronchery SSL_free(new);
407*e7be843bSPierre Pronchery #endif
408*e7be843bSPierre Pronchery return ret;
409*e7be843bSPierre Pronchery }
410*e7be843bSPierre Pronchery
SSL_get1_compressed_cert(SSL * ssl,int alg,unsigned char ** data,size_t * orig_len)411*e7be843bSPierre Pronchery size_t SSL_get1_compressed_cert(SSL *ssl, int alg, unsigned char **data, size_t *orig_len)
412*e7be843bSPierre Pronchery {
413*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
414*e7be843bSPierre Pronchery SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
415*e7be843bSPierre Pronchery CERT_PKEY *cpk = NULL;
416*e7be843bSPierre Pronchery
417*e7be843bSPierre Pronchery if (sc == NULL)
418*e7be843bSPierre Pronchery return 0;
419*e7be843bSPierre Pronchery
420*e7be843bSPierre Pronchery if (sc->cert != NULL)
421*e7be843bSPierre Pronchery cpk = sc->cert->key;
422*e7be843bSPierre Pronchery else
423*e7be843bSPierre Pronchery cpk = ssl->ctx->cert->key;
424*e7be843bSPierre Pronchery
425*e7be843bSPierre Pronchery return ssl_get_compressed_cert(ssl, cpk, alg, data, orig_len);
426*e7be843bSPierre Pronchery #else
427*e7be843bSPierre Pronchery return 0;
428*e7be843bSPierre Pronchery #endif
429*e7be843bSPierre Pronchery }
430*e7be843bSPierre Pronchery
SSL_CTX_get1_compressed_cert(SSL_CTX * ctx,int alg,unsigned char ** data,size_t * orig_len)431*e7be843bSPierre Pronchery size_t SSL_CTX_get1_compressed_cert(SSL_CTX *ctx, int alg, unsigned char **data, size_t *orig_len)
432*e7be843bSPierre Pronchery {
433*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
434*e7be843bSPierre Pronchery size_t ret;
435*e7be843bSPierre Pronchery SSL *new = SSL_new(ctx);
436*e7be843bSPierre Pronchery
437*e7be843bSPierre Pronchery ret = ssl_get_compressed_cert(new, ctx->cert->key, alg, data, orig_len);
438*e7be843bSPierre Pronchery SSL_free(new);
439*e7be843bSPierre Pronchery return ret;
440*e7be843bSPierre Pronchery #else
441*e7be843bSPierre Pronchery return 0;
442*e7be843bSPierre Pronchery #endif
443*e7be843bSPierre Pronchery }
444*e7be843bSPierre Pronchery
SSL_CTX_set1_compressed_cert(SSL_CTX * ctx,int algorithm,unsigned char * comp_data,size_t comp_length,size_t orig_length)445*e7be843bSPierre Pronchery int SSL_CTX_set1_compressed_cert(SSL_CTX *ctx, int algorithm, unsigned char *comp_data,
446*e7be843bSPierre Pronchery size_t comp_length, size_t orig_length)
447*e7be843bSPierre Pronchery {
448*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
449*e7be843bSPierre Pronchery return ossl_set1_compressed_cert(ctx->cert, algorithm, comp_data, comp_length, orig_length);
450*e7be843bSPierre Pronchery #else
451*e7be843bSPierre Pronchery return 0;
452*e7be843bSPierre Pronchery #endif
453*e7be843bSPierre Pronchery }
454*e7be843bSPierre Pronchery
SSL_set1_compressed_cert(SSL * ssl,int algorithm,unsigned char * comp_data,size_t comp_length,size_t orig_length)455*e7be843bSPierre Pronchery int SSL_set1_compressed_cert(SSL *ssl, int algorithm, unsigned char *comp_data,
456*e7be843bSPierre Pronchery size_t comp_length, size_t orig_length)
457*e7be843bSPierre Pronchery {
458*e7be843bSPierre Pronchery #ifndef OPENSSL_NO_COMP_ALG
459*e7be843bSPierre Pronchery SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
460*e7be843bSPierre Pronchery
461*e7be843bSPierre Pronchery /* Cannot set a pre-compressed certificate on a client */
462*e7be843bSPierre Pronchery if (sc == NULL || !sc->server)
463*e7be843bSPierre Pronchery return 0;
464*e7be843bSPierre Pronchery
465*e7be843bSPierre Pronchery return ossl_set1_compressed_cert(sc->cert, algorithm, comp_data, comp_length, orig_length);
466*e7be843bSPierre Pronchery #else
467*e7be843bSPierre Pronchery return 0;
468*e7be843bSPierre Pronchery #endif
469*e7be843bSPierre Pronchery }
470