[csproj] Update project files
[mono-project.git] / mono / btls / btls-x509.c
blob9f378bf6511fd96bcdd3c969ccd42583cb1b99be
1 //
2 // btls-x509.c
3 // MonoBtls
4 //
5 // Created by Martin Baulig on 14/11/15.
6 // Copyright (c) 2015 Xamarin. All rights reserved.
7 //
9 #include "btls-x509.h"
10 #include <openssl/x509v3.h>
11 #include <openssl/pkcs12.h>
13 MONO_API X509 *
14 mono_btls_x509_from_data (const void *buf, int len, MonoBtlsX509Format format)
16 BIO *bio;
17 X509 *cert = NULL;
19 bio = BIO_new_mem_buf ((void *)buf, len);
20 switch (format) {
21 case MONO_BTLS_X509_FORMAT_DER:
22 cert = d2i_X509_bio (bio, NULL);
23 break;
24 case MONO_BTLS_X509_FORMAT_PEM:
25 cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL);
26 break;
28 BIO_free (bio);
29 return cert;
32 MONO_API X509 *
33 mono_btls_x509_up_ref (X509 *x509)
35 X509_up_ref (x509);
36 return x509;
39 MONO_API void
40 mono_btls_x509_free (X509 *x509)
42 X509_free (x509);
45 MONO_API X509 *
46 mono_btls_x509_dup (X509 *x509)
48 return X509_dup (x509);
51 MONO_API MonoBtlsX509Name *
52 mono_btls_x509_get_subject_name (X509 *x509)
54 return mono_btls_x509_name_copy (X509_get_subject_name (x509));
57 MONO_API MonoBtlsX509Name *
58 mono_btls_x509_get_issuer_name (X509 *x509)
60 return mono_btls_x509_name_copy (X509_get_issuer_name (x509));
63 MONO_API int
64 mono_btls_x509_get_subject_name_string (X509 *name, char *buffer, int size)
66 *buffer = 0;
67 return X509_NAME_oneline (X509_get_subject_name (name), buffer, size) != NULL;
70 MONO_API int
71 mono_btls_x509_get_issuer_name_string (X509 *name, char *buffer, int size)
73 *buffer = 0;
74 return X509_NAME_oneline (X509_get_issuer_name (name), buffer, size) != NULL;
77 MONO_API int
78 mono_btls_x509_get_raw_data (X509 *x509, BIO *bio, MonoBtlsX509Format format)
80 switch (format) {
81 case MONO_BTLS_X509_FORMAT_DER:
82 return i2d_X509_bio (bio, x509);
83 case MONO_BTLS_X509_FORMAT_PEM:
84 return PEM_write_bio_X509 (bio, x509);
85 default:
86 return 0;
90 MONO_API int
91 mono_btls_x509_cmp (const X509 *a, const X509 *b)
93 return X509_cmp (a, b);
96 MONO_API int
97 mono_btls_x509_get_hash (X509 *x509, const void **data)
99 X509_check_purpose (x509, -1, 0);
100 *data = x509->sha1_hash;
101 return SHA_DIGEST_LENGTH;
104 MONO_API int64_t
105 mono_btls_x509_get_not_before (X509 *x509)
107 return mono_btls_util_asn1_time_to_ticks (X509_get_notBefore (x509));
110 MONO_API int64_t
111 mono_btls_x509_get_not_after (X509 *x509)
113 return mono_btls_util_asn1_time_to_ticks (X509_get_notAfter (x509));
116 MONO_API int
117 mono_btls_x509_get_public_key (X509 *x509, BIO *bio)
119 ASN1_BIT_STRING *pkey;
120 const unsigned char *data;
121 int ret, data_length;
123 if (!x509 || !x509->cert_info || !x509->cert_info->key)
124 return -1;
126 pkey = x509->cert_info->key->public_key;
127 if (!pkey || !pkey->data)
128 return -1;
130 ret = BIO_write (bio, pkey->data, pkey->length);
131 if (ret != pkey->length)
132 return -1;
134 return ret;
137 MONO_API int
138 mono_btls_x509_get_serial_number (X509 *x509, char *buffer, int size, int mono_style)
140 ASN1_INTEGER *serial;
141 unsigned char *temp, *p;
142 int len, idx;
144 serial = X509_get_serialNumber (x509);
145 if (serial->length == 0 || serial->length+1 > size)
146 return 0;
148 if (!mono_style) {
149 memcpy (buffer, serial->data, serial->length);
150 return serial->length;
153 temp = OPENSSL_malloc (serial->length + 1);
154 if (!temp)
155 return 0;
157 p = temp;
158 len = i2c_ASN1_INTEGER (serial, &p);
160 if (!len) {
161 OPENSSL_free (temp);
162 return 0;
165 memcpy (buffer, temp, len);
166 buffer [len] = 0;
168 OPENSSL_free (temp);
169 return len;
172 MONO_API int
173 mono_btls_x509_get_public_key_algorithm (X509 *x509, char *buffer, int size)
175 X509_PUBKEY *pkey;
176 ASN1_OBJECT *ppkalg;
177 int ret;
179 *buffer = 0;
180 pkey = X509_get_X509_PUBKEY (x509);
181 if (!pkey)
182 return 0;
184 ret = X509_PUBKEY_get0_param (&ppkalg, NULL, NULL, NULL, pkey);
185 if (!ret || !ppkalg)
186 return ret;
188 return OBJ_obj2txt (buffer, size, ppkalg, 1);
191 MONO_API int
192 mono_btls_x509_get_version (X509 *x509)
194 return (int)X509_get_version (x509) + 1;
197 MONO_API int
198 mono_btls_x509_get_signature_algorithm (X509 *x509, char *buffer, int size)
200 const ASN1_OBJECT *obj;
201 int nid;
203 *buffer = 0;
205 nid = X509_get_signature_nid (x509);
207 obj = OBJ_nid2obj (nid);
208 if (!obj)
209 return 0;
211 return OBJ_obj2txt (buffer, size, obj, 1);
214 MONO_API int
215 mono_btls_x509_get_public_key_asn1 (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size)
217 X509_PUBKEY *pkey;
218 ASN1_OBJECT *ppkalg;
219 const unsigned char *pk;
220 int pk_len;
221 int ret;
223 if (out_oid)
224 *out_oid = 0;
226 pkey = X509_get_X509_PUBKEY (x509);
227 if (!pkey || !pkey->public_key)
228 return 0;
230 ret = X509_PUBKEY_get0_param (&ppkalg, &pk, &pk_len, NULL, pkey);
231 if (ret != 1 || !ppkalg || !pk)
232 return 0;
234 if (out_oid) {
235 OBJ_obj2txt (out_oid, oid_len, ppkalg, 1);
238 if (buffer) {
239 *size = pk_len;
240 *buffer = OPENSSL_malloc (pk_len);
241 if (!*buffer)
242 return 0;
244 memcpy (*buffer, pk, pk_len);
247 return 1;
251 MONO_API int
252 mono_btls_x509_get_public_key_parameters (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size)
254 X509_PUBKEY *pkey;
255 X509_ALGOR *algor;
256 ASN1_OBJECT *paobj;
257 int ptype;
258 void *pval;
259 int ret;
261 if (out_oid)
262 *out_oid = 0;
264 pkey = X509_get_X509_PUBKEY (x509);
266 ret = X509_PUBKEY_get0_param (NULL, NULL, NULL, &algor, pkey);
267 if (ret != 1 || !algor)
268 return 0;
270 X509_ALGOR_get0 (&paobj, &ptype, &pval, algor);
272 if (ptype != V_ASN1_NULL && ptype != V_ASN1_SEQUENCE)
273 return 0;
275 if (ptype == V_ASN1_NULL) {
276 uint8_t *ptr;
278 *size = 2;
279 *buffer = OPENSSL_malloc (2);
280 if (!*buffer)
281 return 0;
283 ptr = *buffer;
284 *ptr++ = 0x05;
285 *ptr++ = 0x00;
287 if (out_oid)
288 OBJ_obj2txt (out_oid, oid_len, paobj, 1);
290 return 1;
291 } else if (ptype == V_ASN1_SEQUENCE) {
292 ASN1_STRING *pstr = pval;
294 *size = pstr->length;
295 *buffer = OPENSSL_malloc (pstr->length);
296 if (!*buffer)
297 return 0;
299 memcpy (*buffer, pstr->data, pstr->length);
301 if (out_oid)
302 OBJ_obj2txt (out_oid, oid_len, paobj, 1);
304 return 1;
305 } else {
306 return 0;
310 MONO_API EVP_PKEY *
311 mono_btls_x509_get_pubkey (X509 *x509)
313 return X509_get_pubkey (x509);
316 MONO_API int
317 mono_btls_x509_get_subject_key_identifier (X509 *x509, uint8_t **buffer, int *size)
319 ASN1_OCTET_STRING *skid;
321 *size = 0;
322 *buffer = NULL;
324 if (X509_get_version (x509) != 2)
325 return 0;
327 skid = X509_get_ext_d2i (x509, NID_subject_key_identifier, NULL, NULL);
328 if (!skid)
329 return 0;
331 *size = skid->length;
332 *buffer = OPENSSL_malloc (*size);
333 if (!*buffer)
334 return 0;
336 memcpy (*buffer, skid->data, *size);
337 return 1;
340 MONO_API int
341 mono_btls_x509_print (X509 *x509, BIO *bio)
343 return X509_print_ex (bio, x509, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
346 static int
347 get_trust_nid (MonoBtlsX509Purpose purpose)
349 switch (purpose) {
350 case MONO_BTLS_X509_PURPOSE_SSL_CLIENT:
351 return NID_client_auth;
352 case MONO_BTLS_X509_PURPOSE_SSL_SERVER:
353 return NID_server_auth;
354 default:
355 return 0;
359 MONO_API int
360 mono_btls_x509_add_trust_object (X509 *x509, MonoBtlsX509Purpose purpose)
362 ASN1_OBJECT *trust;
363 int nid;
365 nid = get_trust_nid (purpose);
366 if (!nid)
367 return 0;
369 trust = ASN1_OBJECT_new ();
370 if (!trust)
371 return 0;
373 trust->nid = nid;
374 return X509_add1_trust_object (x509, trust);
377 MONO_API int
378 mono_btls_x509_add_reject_object (X509 *x509, MonoBtlsX509Purpose purpose)
380 ASN1_OBJECT *reject;
381 int nid;
383 nid = get_trust_nid (purpose);
384 if (!nid)
385 return 0;
387 reject = ASN1_OBJECT_new ();
388 if (!reject)
389 return 0;
391 reject->nid = nid;
392 return X509_add1_reject_object (x509, reject);
395 MONO_API int
396 mono_btls_x509_add_explicit_trust (X509 *x509, MonoBtlsX509TrustKind kind)
398 int ret = 0;
400 if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_ALL) != 0)
401 kind |= MONO_BTLS_X509_TRUST_KIND_REJECT_CLIENT | MONO_BTLS_X509_TRUST_KIND_REJECT_SERVER;
403 if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_ALL) != 0)
404 kind |= MONO_BTLS_X509_TRUST_KIND_TRUST_CLIENT | MONO_BTLS_X509_TRUST_KIND_TRUST_SERVER;
407 if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_CLIENT) != 0) {
408 ret = mono_btls_x509_add_reject_object (x509, MONO_BTLS_X509_PURPOSE_SSL_CLIENT);
409 if (!ret)
410 return ret;
413 if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_SERVER) != 0) {
414 ret = mono_btls_x509_add_reject_object (x509, MONO_BTLS_X509_PURPOSE_SSL_SERVER);
415 if (!ret)
416 return ret;
419 if (ret) {
420 // Ignore any MONO_BTLS_X509_TRUST_KIND_TRUST_* settings if we added
421 // any kind of MONO_BTLS_X509_TRUST_KIND_REJECT_* before.
422 return ret;
425 if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_CLIENT) != 0) {
426 ret = mono_btls_x509_add_trust_object (x509, MONO_BTLS_X509_PURPOSE_SSL_CLIENT);
427 if (!ret)
428 return ret;
431 if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_SERVER) != 0) {
432 ret = mono_btls_x509_add_trust_object (x509, MONO_BTLS_X509_PURPOSE_SSL_SERVER);
433 if (!ret)
434 return ret;
437 return ret;