ip: Replace Sematics for Interface IP addresses
[vpp.git] / src / plugins / tlspicotls / certs.c
1 #include <openssl/pem.h>
2 #include <vppinfra/error.h>
3 #include "certs.h"
4
5 int
6 ptls_compare_separator_line (const char *line, const char *begin_or_end,
7                              const char *label)
8 {
9   int ret = strncmp (line, "-----", 5);
10   size_t text_index = 5;
11
12   if (ret == 0)
13     {
14       size_t begin_or_end_length = strlen (begin_or_end);
15       ret = strncmp (line + text_index, begin_or_end, begin_or_end_length);
16       text_index += begin_or_end_length;
17     }
18
19   if (ret == 0)
20     {
21       ret = line[text_index] - ' ';
22       text_index++;
23     }
24
25   if (ret == 0)
26     {
27       size_t label_length = strlen (label);
28       ret = strncmp (line + text_index, label, label_length);
29       text_index += label_length;
30     }
31
32   if (ret == 0)
33     {
34       ret = strncmp (line + text_index, "-----", 5);
35     }
36
37   return ret;
38 }
39
40 int
41 ptls_get_bio_pem_object (BIO * bio, const char *label, ptls_buffer_t * buf)
42 {
43   int ret = PTLS_ERROR_PEM_LABEL_NOT_FOUND;
44   char line[256];
45   ptls_base64_decode_state_t state;
46
47   /* Get the label on a line by itself */
48   while (BIO_gets (bio, line, 256))
49     {
50       if (ptls_compare_separator_line (line, "BEGIN", label) == 0)
51         {
52           ret = 0;
53           ptls_base64_decode_init (&state);
54           break;
55         }
56     }
57   /* Get the data in the buffer */
58   while (ret == 0 && BIO_gets (bio, line, 256))
59     {
60       if (ptls_compare_separator_line (line, "END", label) == 0)
61         {
62           if (state.status == PTLS_BASE64_DECODE_DONE
63               || (state.status == PTLS_BASE64_DECODE_IN_PROGRESS
64                   && state.nbc == 0))
65             {
66               ret = 0;
67             }
68           else
69             {
70               ret = PTLS_ERROR_INCORRECT_BASE64;
71             }
72           break;
73         }
74       else
75         {
76           ret = ptls_base64_decode (line, &state, buf);
77         }
78     }
79
80   return ret;
81 }
82
83 int
84 ptls_load_bio_pem_objects (BIO * bio, const char *label, ptls_iovec_t * list,
85                            size_t list_max, size_t * nb_objects)
86 {
87   int ret = 0;
88   size_t count = 0;
89
90   *nb_objects = 0;
91
92   if (ret == 0)
93     {
94       while (count < list_max)
95         {
96           ptls_buffer_t buf;
97
98           ptls_buffer_init (&buf, "", 0);
99
100           ret = ptls_get_bio_pem_object (bio, label, &buf);
101
102           if (ret == 0)
103             {
104               if (buf.off > 0 && buf.is_allocated)
105                 {
106                   list[count].base = buf.base;
107                   list[count].len = buf.off;
108                   count++;
109                 }
110               else
111                 {
112                   ptls_buffer_dispose (&buf);
113                 }
114             }
115           else
116             {
117               ptls_buffer_dispose (&buf);
118               break;
119             }
120         }
121     }
122
123   if (ret == PTLS_ERROR_PEM_LABEL_NOT_FOUND && count > 0)
124     {
125       ret = 0;
126     }
127
128   *nb_objects = count;
129
130   return ret;
131 }
132
133 #define PTLS_MAX_CERTS_IN_CONTEXT 16
134
135 int
136 ptls_load_bio_certificates (ptls_context_t * ctx, BIO * bio)
137 {
138   int ret = 0;
139
140   ctx->certificates.list =
141     (ptls_iovec_t *) malloc (PTLS_MAX_CERTS_IN_CONTEXT *
142                              sizeof (ptls_iovec_t));
143
144   if (ctx->certificates.list == NULL)
145     {
146       ret = PTLS_ERROR_NO_MEMORY;
147     }
148   else
149     {
150       ret =
151         ptls_load_bio_pem_objects (bio, "CERTIFICATE", ctx->certificates.list,
152                                    PTLS_MAX_CERTS_IN_CONTEXT,
153                                    &ctx->certificates.count);
154     }
155
156   return ret;
157 }
158
159 int
160 load_bio_certificate_chain (ptls_context_t * ctx, const char *cert_data)
161 {
162   BIO *cert_bio;
163   cert_bio = BIO_new_mem_buf (cert_data, -1);
164   if (ptls_load_bio_certificates (ctx, cert_bio) != 0)
165     {
166       BIO_free (cert_bio);
167       return -1;
168     }
169   BIO_free (cert_bio);
170   return 0;
171 }
172
173 int
174 load_bio_private_key (ptls_context_t * ctx, const char *pk_data)
175 {
176   static ptls_openssl_sign_certificate_t sc;
177   EVP_PKEY *pkey;
178   BIO *key_bio;
179
180   key_bio = BIO_new_mem_buf (pk_data, -1);
181   pkey = PEM_read_bio_PrivateKey (key_bio, NULL, NULL, NULL);
182   BIO_free (key_bio);
183
184   if (pkey == NULL)
185     return -1;
186
187   ptls_openssl_init_sign_certificate (&sc, pkey);
188   EVP_PKEY_free (pkey);
189
190   ctx->sign_certificate = &sc.super;
191   return 0;
192 }
193
194 /*
195  * fd.io coding-style-patch-verification: ON
196  *
197  * Local Variables:
198  * eval: (c-set-style "gnu")
199  * End:
200  */