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);
52 mono_btls_x509_get_subject_name (X509 *x509)
54 return mono_btls_x509_name_copy (X509_get_subject_name (x509));
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)
120 uint8_t *data = NULL;
123 pkey = X509_get_pubkey (x509);
127 ret = i2d_PublicKey (pkey, &data);
129 if (ret > 0 && data) {
130 ret = BIO_write (bio, data, ret);
134 EVP_PKEY_free (pkey);
139 mono_btls_x509_get_serial_number (X509 *x509, char *buffer, int size, int mono_style)
141 ASN1_INTEGER *serial;
145 serial = X509_get_serialNumber (x509);
146 if (serial->length == 0 || serial->length+1 > size)
150 memcpy (buffer, serial->data, serial->length);
151 return serial->length;
157 for (idx = serial->length - 1; idx >= 0; idx--) {
158 *pos++ = serial->data [idx];
162 if (serial->data [0] >= 0x80) {
171 mono_btls_x509_get_public_key_algorithm (X509 *x509, char *buffer, int size)
178 pkey = X509_get_X509_PUBKEY (x509);
182 ret = X509_PUBKEY_get0_param (&ppkalg, NULL, NULL, NULL, pkey);
186 return OBJ_obj2txt (buffer, size, ppkalg, 1);
190 mono_btls_x509_get_version (X509 *x509)
192 return (int)X509_get_version (x509) + 1;
196 mono_btls_x509_get_signature_algorithm (X509 *x509, char *buffer, int size)
198 const ASN1_OBJECT *obj;
203 nid = X509_get_signature_nid (x509);
205 obj = OBJ_nid2obj (nid);
209 return OBJ_obj2txt (buffer, size, obj, 1);
213 mono_btls_x509_get_public_key_asn1 (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size)
217 const unsigned char *pk;
224 pkey = X509_get_X509_PUBKEY (x509);
225 if (!pkey || !pkey->public_key)
228 ret = X509_PUBKEY_get0_param (&ppkalg, &pk, &pk_len, NULL, pkey);
229 if (ret != 1 || !ppkalg || !pk)
233 OBJ_obj2txt (out_oid, oid_len, ppkalg, 1);
238 *buffer = OPENSSL_malloc (pk_len);
242 memcpy (*buffer, pk, pk_len);
250 mono_btls_x509_get_public_key_parameters (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size)
262 pkey = X509_get_X509_PUBKEY (x509);
264 ret = X509_PUBKEY_get0_param (NULL, NULL, NULL, &algor, pkey);
265 if (ret != 1 || !algor)
268 X509_ALGOR_get0 (&paobj, &ptype, &pval, algor);
270 if (ptype != V_ASN1_NULL && ptype != V_ASN1_SEQUENCE)
273 if (ptype == V_ASN1_NULL) {
277 *buffer = OPENSSL_malloc (2);
286 OBJ_obj2txt (out_oid, oid_len, paobj, 1);
289 } else if (ptype == V_ASN1_SEQUENCE) {
290 ASN1_STRING *pstr = pval;
292 *size = pstr->length;
293 *buffer = OPENSSL_malloc (pstr->length);
297 memcpy (*buffer, pstr->data, pstr->length);
300 OBJ_obj2txt (out_oid, oid_len, paobj, 1);
309 mono_btls_x509_get_pubkey (X509 *x509)
311 return X509_get_pubkey (x509);
315 mono_btls_x509_get_subject_key_identifier (X509 *x509, uint8_t **buffer, int *size)
317 ASN1_OCTET_STRING *skid;
322 if (X509_get_version (x509) != 2)
325 skid = X509_get_ext_d2i (x509, NID_subject_key_identifier, NULL, NULL);
329 *size = skid->length;
330 *buffer = OPENSSL_malloc (*size);
334 memcpy (*buffer, skid->data, *size);
339 mono_btls_x509_print (X509 *x509, BIO *bio)
341 return X509_print_ex (bio, x509, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
345 get_trust_nid (MonoBtlsX509Purpose purpose)
348 case MONO_BTLS_X509_PURPOSE_SSL_CLIENT:
349 return NID_client_auth;
350 case MONO_BTLS_X509_PURPOSE_SSL_SERVER:
351 return NID_server_auth;
358 mono_btls_x509_add_trust_object (X509 *x509, MonoBtlsX509Purpose purpose)
363 nid = get_trust_nid (purpose);
367 trust = ASN1_OBJECT_new ();
372 return X509_add1_trust_object (x509, trust);
376 mono_btls_x509_add_reject_object (X509 *x509, MonoBtlsX509Purpose purpose)
381 nid = get_trust_nid (purpose);
385 reject = ASN1_OBJECT_new ();
390 return X509_add1_reject_object (x509, reject);
394 mono_btls_x509_add_explicit_trust (X509 *x509, MonoBtlsX509TrustKind kind)
398 if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_ALL) != 0)
399 kind |= MONO_BTLS_X509_TRUST_KIND_REJECT_CLIENT | MONO_BTLS_X509_TRUST_KIND_REJECT_SERVER;
401 if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_ALL) != 0)
402 kind |= MONO_BTLS_X509_TRUST_KIND_TRUST_CLIENT | MONO_BTLS_X509_TRUST_KIND_TRUST_SERVER;
405 if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_CLIENT) != 0) {
406 ret = mono_btls_x509_add_reject_object (x509, MONO_BTLS_X509_PURPOSE_SSL_CLIENT);
411 if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_SERVER) != 0) {
412 ret = mono_btls_x509_add_reject_object (x509, MONO_BTLS_X509_PURPOSE_SSL_SERVER);
418 // Ignore any MONO_BTLS_X509_TRUST_KIND_TRUST_* settings if we added
419 // any kind of MONO_BTLS_X509_TRUST_KIND_REJECT_* before.
423 if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_CLIENT) != 0) {
424 ret = mono_btls_x509_add_trust_object (x509, MONO_BTLS_X509_PURPOSE_SSL_CLIENT);
429 if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_SERVER) != 0) {
430 ret = mono_btls_x509_add_trust_object (x509, MONO_BTLS_X509_PURPOSE_SSL_SERVER);