5 // Created by Martin Baulig on 14/11/15.
6 // Copyright (c) 2015 Xamarin. All rights reserved.
10 #include <openssl/x509v3.h>
11 #include <openssl/pkcs12.h>
14 mono_btls_x509_from_data (const void *buf
, int len
, MonoBtlsX509Format format
)
19 bio
= BIO_new_mem_buf ((void *)buf
, len
);
21 case MONO_BTLS_X509_FORMAT_DER
:
22 cert
= d2i_X509_bio (bio
, NULL
);
24 case MONO_BTLS_X509_FORMAT_PEM
:
25 cert
= PEM_read_bio_X509 (bio
, NULL
, NULL
, NULL
);
33 mono_btls_x509_up_ref (X509
*x509
)
40 mono_btls_x509_free (X509
*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
));
64 mono_btls_x509_get_subject_name_string (X509
*name
, char *buffer
, int size
)
67 return X509_NAME_oneline (X509_get_subject_name (name
), buffer
, size
) != NULL
;
71 mono_btls_x509_get_issuer_name_string (X509
*name
, char *buffer
, int size
)
74 return X509_NAME_oneline (X509_get_issuer_name (name
), buffer
, size
) != NULL
;
78 mono_btls_x509_get_raw_data (X509
*x509
, BIO
*bio
, MonoBtlsX509Format 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
);
91 mono_btls_x509_cmp (const X509
*a
, const X509
*b
)
93 return X509_cmp (a
, b
);
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
;
105 mono_btls_x509_get_not_before (X509
*x509
)
107 return mono_btls_util_asn1_time_to_ticks (X509_get_notBefore (x509
));
111 mono_btls_x509_get_not_after (X509
*x509
)
113 return mono_btls_util_asn1_time_to_ticks (X509_get_notAfter (x509
));
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
)
126 pkey
= x509
->cert_info
->key
->public_key
;
127 if (!pkey
|| !pkey
->data
)
130 ret
= BIO_write (bio
, pkey
->data
, pkey
->length
);
131 if (ret
!= pkey
->length
)
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
;
144 serial
= X509_get_serialNumber (x509
);
145 if (serial
->length
== 0 || serial
->length
+1 > size
)
149 memcpy (buffer
, serial
->data
, serial
->length
);
150 return serial
->length
;
153 temp
= OPENSSL_malloc (serial
->length
+ 1);
158 len
= i2c_ASN1_INTEGER (serial
, &p
);
165 memcpy (buffer
, temp
, len
);
173 mono_btls_x509_get_public_key_algorithm (X509
*x509
, char *buffer
, int size
)
180 pkey
= X509_get_X509_PUBKEY (x509
);
184 ret
= X509_PUBKEY_get0_param (&ppkalg
, NULL
, NULL
, NULL
, pkey
);
188 return OBJ_obj2txt (buffer
, size
, ppkalg
, 1);
192 mono_btls_x509_get_version (X509
*x509
)
194 return (int)X509_get_version (x509
) + 1;
198 mono_btls_x509_get_signature_algorithm (X509
*x509
, char *buffer
, int size
)
200 const ASN1_OBJECT
*obj
;
205 nid
= X509_get_signature_nid (x509
);
207 obj
= OBJ_nid2obj (nid
);
211 return OBJ_obj2txt (buffer
, size
, obj
, 1);
215 mono_btls_x509_get_public_key_asn1 (X509
*x509
, char *out_oid
, int oid_len
, uint8_t **buffer
, int *size
)
219 const unsigned char *pk
;
226 pkey
= X509_get_X509_PUBKEY (x509
);
227 if (!pkey
|| !pkey
->public_key
)
230 ret
= X509_PUBKEY_get0_param (&ppkalg
, &pk
, &pk_len
, NULL
, pkey
);
231 if (ret
!= 1 || !ppkalg
|| !pk
)
235 OBJ_obj2txt (out_oid
, oid_len
, ppkalg
, 1);
240 *buffer
= OPENSSL_malloc (pk_len
);
244 memcpy (*buffer
, pk
, pk_len
);
252 mono_btls_x509_get_public_key_parameters (X509
*x509
, char *out_oid
, int oid_len
, uint8_t **buffer
, int *size
)
264 pkey
= X509_get_X509_PUBKEY (x509
);
266 ret
= X509_PUBKEY_get0_param (NULL
, NULL
, NULL
, &algor
, pkey
);
267 if (ret
!= 1 || !algor
)
270 X509_ALGOR_get0 (&paobj
, &ptype
, &pval
, algor
);
272 if (ptype
!= V_ASN1_NULL
&& ptype
!= V_ASN1_SEQUENCE
)
275 if (ptype
== V_ASN1_NULL
) {
279 *buffer
= OPENSSL_malloc (2);
288 OBJ_obj2txt (out_oid
, oid_len
, paobj
, 1);
291 } else if (ptype
== V_ASN1_SEQUENCE
) {
292 ASN1_STRING
*pstr
= pval
;
294 *size
= pstr
->length
;
295 *buffer
= OPENSSL_malloc (pstr
->length
);
299 memcpy (*buffer
, pstr
->data
, pstr
->length
);
302 OBJ_obj2txt (out_oid
, oid_len
, paobj
, 1);
311 mono_btls_x509_get_pubkey (X509
*x509
)
313 return X509_get_pubkey (x509
);
317 mono_btls_x509_get_subject_key_identifier (X509
*x509
, uint8_t **buffer
, int *size
)
319 ASN1_OCTET_STRING
*skid
;
324 if (X509_get_version (x509
) != 2)
327 skid
= X509_get_ext_d2i (x509
, NID_subject_key_identifier
, NULL
, NULL
);
331 *size
= skid
->length
;
332 *buffer
= OPENSSL_malloc (*size
);
336 memcpy (*buffer
, skid
->data
, *size
);
341 mono_btls_x509_print (X509
*x509
, BIO
*bio
)
343 return X509_print_ex (bio
, x509
, XN_FLAG_COMPAT
, X509_FLAG_COMPAT
);
347 get_trust_nid (MonoBtlsX509Purpose 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
;
360 mono_btls_x509_add_trust_object (X509
*x509
, MonoBtlsX509Purpose purpose
)
365 nid
= get_trust_nid (purpose
);
369 trust
= ASN1_OBJECT_new ();
374 return X509_add1_trust_object (x509
, trust
);
378 mono_btls_x509_add_reject_object (X509
*x509
, MonoBtlsX509Purpose purpose
)
383 nid
= get_trust_nid (purpose
);
387 reject
= ASN1_OBJECT_new ();
392 return X509_add1_reject_object (x509
, reject
);
396 mono_btls_x509_add_explicit_trust (X509
*x509
, MonoBtlsX509TrustKind kind
)
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
);
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
);
420 // Ignore any MONO_BTLS_X509_TRUST_KIND_TRUST_* settings if we added
421 // any kind of MONO_BTLS_X509_TRUST_KIND_REJECT_* before.
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
);
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
);