FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
certs.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <openssl/pem.h>
17 
18 #include <vppinfra/error.h>
19 
20 #include <quic/certs.h>
21 
22 
23 int
24 ptls_compare_separator_line (const char *line, const char *begin_or_end,
25  const char *label)
26 {
27  int ret = strncmp (line, "-----", 5);
28  size_t text_index = 5;
29 
30  if (ret == 0)
31  {
32  size_t begin_or_end_length = strlen (begin_or_end);
33  ret = strncmp (line + text_index, begin_or_end, begin_or_end_length);
34  text_index += begin_or_end_length;
35  }
36 
37  if (ret == 0)
38  {
39  ret = line[text_index] - ' ';
40  text_index++;
41  }
42 
43  if (ret == 0)
44  {
45  size_t label_length = strlen (label);
46  ret = strncmp (line + text_index, label, label_length);
47  text_index += label_length;
48  }
49 
50  if (ret == 0)
51  {
52  ret = strncmp (line + text_index, "-----", 5);
53  }
54 
55  return ret;
56 }
57 
58 int
59 ptls_get_bio_pem_object (BIO * bio, const char *label, ptls_buffer_t * buf)
60 {
61  int ret = PTLS_ERROR_PEM_LABEL_NOT_FOUND;
62  char line[256];
63  ptls_base64_decode_state_t state;
64 
65  /* Get the label on a line by itself */
66  while (BIO_gets (bio, line, 256))
67  {
68  if (ptls_compare_separator_line (line, "BEGIN", label) == 0)
69  {
70  ret = 0;
71  ptls_base64_decode_init (&state);
72  break;
73  }
74  }
75  /* Get the data in the buffer */
76  while (ret == 0 && BIO_gets (bio, line, 256))
77  {
78  if (ptls_compare_separator_line (line, "END", label) == 0)
79  {
80  if (state.status == PTLS_BASE64_DECODE_DONE
81  || (state.status == PTLS_BASE64_DECODE_IN_PROGRESS
82  && state.nbc == 0))
83  {
84  ret = 0;
85  }
86  else
87  {
88  ret = PTLS_ERROR_INCORRECT_BASE64;
89  }
90  break;
91  }
92  else
93  {
94  ret = ptls_base64_decode (line, &state, buf);
95  }
96  }
97 
98  return ret;
99 }
100 
101 int
102 ptls_load_bio_pem_objects (BIO * bio, const char *label, ptls_iovec_t * list,
103  size_t list_max, size_t * nb_objects)
104 {
105  int ret = 0;
106  size_t count = 0;
107 
108  *nb_objects = 0;
109 
110  if (ret == 0)
111  {
112  while (count < list_max)
113  {
114  ptls_buffer_t buf;
115 
116  ptls_buffer_init (&buf, "", 0);
117 
118  ret = ptls_get_bio_pem_object (bio, label, &buf);
119 
120  if (ret == 0)
121  {
122  if (buf.off > 0 && buf.is_allocated)
123  {
124  list[count].base = buf.base;
125  list[count].len = buf.off;
126  count++;
127  }
128  else
129  {
130  ptls_buffer_dispose (&buf);
131  }
132  }
133  else
134  {
135  ptls_buffer_dispose (&buf);
136  break;
137  }
138  }
139  }
140 
141  if (ret == PTLS_ERROR_PEM_LABEL_NOT_FOUND && count > 0)
142  {
143  ret = 0;
144  }
145 
146  *nb_objects = count;
147 
148  return ret;
149 }
150 
151 #define PTLS_MAX_CERTS_IN_CONTEXT 16
152 
153 int
154 ptls_load_bio_certificates (ptls_context_t * ctx, BIO * bio)
155 {
156  int ret = 0;
157 
158  ctx->certificates.list =
159  (ptls_iovec_t *) malloc (PTLS_MAX_CERTS_IN_CONTEXT *
160  sizeof (ptls_iovec_t));
161 
162  if (ctx->certificates.list == NULL)
163  {
164  ret = PTLS_ERROR_NO_MEMORY;
165  }
166  else
167  {
168  ret =
169  ptls_load_bio_pem_objects (bio, "CERTIFICATE", ctx->certificates.list,
171  &ctx->certificates.count);
172  }
173 
174  return ret;
175 }
176 
177 int
178 load_bio_certificate_chain (ptls_context_t * ctx, const char *cert_data)
179 {
180  BIO *cert_bio;
181  cert_bio = BIO_new_mem_buf (cert_data, -1);
182  if (ptls_load_bio_certificates (ctx, cert_bio) != 0)
183  {
184  BIO_free (cert_bio);
185  return -1;
186  }
187  BIO_free (cert_bio);
188  return 0;
189 }
190 
191 int
192 load_bio_private_key (ptls_context_t * ctx, const char *pk_data)
193 {
194  static ptls_openssl_sign_certificate_t sc;
195  EVP_PKEY *pkey;
196  BIO *key_bio;
197 
198  key_bio = BIO_new_mem_buf (pk_data, -1);
199  pkey = PEM_read_bio_PrivateKey (key_bio, NULL, NULL, NULL);
200  BIO_free (key_bio);
201 
202  if (pkey == NULL)
203  return -1;
204 
205  ptls_openssl_init_sign_certificate (&sc, pkey);
206  EVP_PKEY_free (pkey);
207 
208  ctx->sign_certificate = &sc.super;
209  return 0;
210 }
u8 count
Definition: dhcp.api:208
#define NULL
Definition: clib.h:58
int ptls_compare_separator_line(const char *line, const char *begin_or_end, const char *label)
Definition: certs.c:24
int ptls_get_bio_pem_object(BIO *bio, const char *label, ptls_buffer_t *buf)
Definition: certs.c:59
int ptls_load_bio_certificates(ptls_context_t *ctx, BIO *bio)
Definition: certs.c:154
long ctx[MAX_CONNS]
Definition: main.c:144
u32 label
Definition: fib_types.api:25
int load_bio_certificate_chain(ptls_context_t *ctx, const char *cert_data)
Definition: certs.c:178
vl_api_dhcp_client_state_t state
Definition: dhcp.api:201
int ptls_load_bio_pem_objects(BIO *bio, const char *label, ptls_iovec_t *list, size_t list_max, size_t *nb_objects)
Definition: certs.c:102
#define PTLS_MAX_CERTS_IN_CONTEXT
Definition: certs.c:151
int load_bio_private_key(ptls_context_t *ctx, const char *pk_data)
Definition: certs.c:192