1// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2//
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#include "private-lib-core.h"
16
17#include "ssl_x509.h"
18#include "ssl_methods.h"
19#include "ssl_dbg.h"
20#include "ssl_port.h"
21
22#include <assert.h>
23
24/**
25 * @brief show X509 certification information
26 */
27int __X509_show_info(X509 *x)
28{
29    return X509_METHOD_CALL(show_info, x);
30}
31
32/**
33 * @brief create a X509 certification object according to input X509 certification
34 */
35X509* __X509_new(X509 *ix)
36{
37    int ret;
38    X509 *x;
39
40    x = ssl_mem_zalloc(sizeof(X509));
41    if (!x) {
42        SSL_DEBUG(SSL_X509_ERROR_LEVEL, "no enough memory > (x)");
43        goto no_mem;
44    }
45
46    if (ix)
47        x->method = ix->method;
48    else
49        x->method = X509_method();
50
51    ret = X509_METHOD_CALL(new, x, ix);
52    if (ret) {
53        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_METHOD_CALL(new) return %d", ret);
54        goto failed;
55    }
56
57    return x;
58
59failed:
60    ssl_mem_free(x);
61no_mem:
62    return NULL;
63}
64
65/**
66 * @brief create a X509 certification object
67 */
68X509* X509_new(void)
69{
70    return __X509_new(NULL);
71}
72
73/**
74 * @brief free a X509 certification object
75 */
76void X509_free(X509 *x)
77{
78    SSL_ASSERT3(x);
79
80    X509_METHOD_CALL(free, x);
81
82    ssl_mem_free(x);
83};
84
85/**
86 * @brief load a character certification context into system context. If '*cert' is pointed to the
87 *        certification, then load certification into it. Or create a new X509 certification object
88 */
89X509* d2i_X509(X509 **cert, const unsigned char *buffer, long len)
90{
91    int m = 0;
92    int ret;
93    X509 *x;
94
95    SSL_ASSERT2(buffer);
96    SSL_ASSERT2(len);
97
98    if (cert && *cert) {
99        x = *cert;
100    } else {
101        x = X509_new();
102        if (!x) {
103            SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_new() return NULL");
104            goto failed1;
105        }
106        m = 1;
107    }
108
109    ret = X509_METHOD_CALL(load, x, buffer, (int)len);
110    if (ret) {
111        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_METHOD_CALL(load) return %d", ret);
112        goto failed2;
113    }
114
115    return x;
116
117failed2:
118    if (m)
119        X509_free(x);
120failed1:
121    return NULL;
122}
123
124/**
125 * @brief return SSL X509 verify parameters
126 */
127
128X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl)
129{
130	return &ssl->param;
131}
132
133/**
134 * @brief set X509 host verification flags
135 */
136
137int X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
138				    unsigned long flags)
139{
140	/* flags not supported yet */
141	return 0;
142}
143
144/**
145 * @brief clear X509 host verification flags
146 */
147
148int X509_VERIFY_PARAM_clear_hostflags(X509_VERIFY_PARAM *param,
149				      unsigned long flags)
150{
151	/* flags not supported yet */
152	return 0;
153}
154
155/**
156 * @brief set SSL context client CA certification
157 */
158int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
159{
160    SSL_ASSERT1(ctx);
161    SSL_ASSERT1(x);
162    assert(ctx);
163    if (ctx->client_CA == x)
164        return 1;
165
166    X509_free(ctx->client_CA);
167
168    ctx->client_CA = x;
169
170    return 1;
171}
172
173/**
174 * @brief add CA client certification into the SSL
175 */
176int SSL_CTX_add_client_CA_ASN1(SSL_CTX *ctx, int len,
177                const unsigned char *d)
178{
179	SSL_ASSERT1(ctx);
180
181	if (!d2i_X509(&ctx->client_CA, d, len)) {
182		SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_X509() return NULL");
183		return 0;
184	}
185
186	return 1;
187}
188
189/**
190 * @brief add CA client certification into the SSL
191 */
192int SSL_add_client_CA(SSL *ssl, X509 *x)
193{
194    SSL_ASSERT1(ssl);
195    SSL_ASSERT1(x);
196
197    if (ssl->client_CA == x)
198        return 1;
199
200    X509_free(ssl->client_CA);
201
202    ssl->client_CA = x;
203
204    return 1;
205}
206
207/**
208 * @brief set the SSL context certification
209 */
210int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
211{
212    SSL_ASSERT1(ctx);
213    SSL_ASSERT1(x);
214
215    if (ctx->cert->x509 == x)
216        return 1;
217
218    X509_free(ctx->cert->x509);
219
220    ctx->cert->x509 = x;
221
222    return 1;
223}
224
225/**
226 * @brief set the SSL certification
227 */
228int SSL_use_certificate(SSL *ssl, X509 *x)
229{
230    SSL_ASSERT1(ssl);
231    SSL_ASSERT1(x);
232
233    if (ssl->cert->x509 == x)
234        return 1;
235
236    X509_free(ssl->cert->x509);
237
238    ssl->cert->x509 = x;
239
240    return 1;
241}
242
243/**
244 * @brief get the SSL certification point
245 */
246X509 *SSL_get_certificate(const SSL *ssl)
247{
248    SSL_ASSERT2(ssl);
249
250    return ssl->cert->x509;
251}
252
253/**
254 * @brief load certification into the SSL context
255 */
256int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
257                                 const unsigned char *d)
258{
259    int ret;
260    X509 *x;
261
262    x = d2i_X509(NULL, d, len);
263    if (!x) {
264        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_X509() return NULL");
265        goto failed1;
266    }
267
268    ret = SSL_CTX_use_certificate(ctx, x);
269    if (!ret) {
270        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_CTX_use_certificate() return %d", ret);
271        goto failed2;
272    }
273
274    return 1;
275
276failed2:
277    X509_free(x);
278failed1:
279    return 0;
280}
281
282/**
283 * @brief load certification into the SSL
284 */
285int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
286{
287    int ret;
288    X509 *x;
289
290    x = d2i_X509(NULL, d, len);
291    if (!x) {
292        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_X509() return NULL");
293        goto failed1;
294    }
295
296    ret = SSL_use_certificate(ssl, x);
297    if (!ret) {
298        SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_use_certificate() return %d", ret);
299        goto failed2;
300    }
301
302    return 1;
303
304failed2:
305    X509_free(x);
306failed1:
307    return 0;
308}
309
310/**
311 * @brief load the certification file into SSL context
312 */
313int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
314{
315    return 0;
316}
317
318/**
319 * @brief load the certification file into SSL
320 */
321int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
322{
323    return 0;
324}
325
326/**
327 * @brief get peer certification
328 */
329X509 *SSL_get_peer_certificate(const SSL *ssl)
330{
331    SSL_ASSERT2(ssl);
332
333    return ssl->session->peer;
334}
335
336int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
337{
338	return X509_V_ERR_UNSPECIFIED;
339}
340
341int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
342{
343	return 0;
344}
345
346const char *X509_verify_cert_error_string(long n)
347{
348	return "unknown";
349}
350