Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / btls / btls-x509-name.c
1 //
2 //  btls-x509-name.c
3 //  MonoBtls
4 //
5 //  Created by Martin Baulig on 3/5/16.
6 //  Copyright © 2016 Xamarin. All rights reserved.
7 //
8
9 #include <btls-x509-name.h>
10
11 struct MonoBtlsX509Name {
12         int owns;
13         X509_NAME *name;
14 };
15
16 MONO_API MonoBtlsX509Name *
17 mono_btls_x509_name_from_name (X509_NAME *xn)
18 {
19         MonoBtlsX509Name *name;
20
21         name = OPENSSL_malloc (sizeof (MonoBtlsX509Name));
22         if (!name)
23                 return NULL;
24
25         memset(name, 0, sizeof(MonoBtlsX509Name));
26         name->name = xn;
27         return name;
28 }
29
30 MONO_API MonoBtlsX509Name *
31 mono_btls_x509_name_copy (X509_NAME *xn)
32 {
33         MonoBtlsX509Name *name;
34
35         name = OPENSSL_malloc (sizeof (MonoBtlsX509Name));
36         if (!name)
37                 return NULL;
38
39         memset(name, 0, sizeof(MonoBtlsX509Name));
40         name->name = X509_NAME_dup(xn);
41         name->owns = 1;
42         return name;
43 }
44
45 MONO_API void
46 mono_btls_x509_name_free (MonoBtlsX509Name *name)
47 {
48         if (name->owns) {
49                 if (name->name) {
50                         X509_NAME_free(name->name);
51                         name->name = NULL;
52                 }
53         }
54         OPENSSL_free(name);
55 }
56
57 MONO_API X509_NAME *
58 mono_btls_x509_name_peek_name (MonoBtlsX509Name *name)
59 {
60         return name->name;
61 }
62
63 MONO_API int
64 mono_btls_x509_name_print_bio (MonoBtlsX509Name *name, BIO *bio)
65 {
66         return X509_NAME_print_ex (bio, name->name, 0, ASN1_STRFLGS_RFC2253 | XN_FLAG_FN_SN | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_DN_REV);
67 }
68
69 MONO_API int
70 mono_btls_x509_name_get_raw_data (MonoBtlsX509Name *name, void **buffer, int use_canon_enc)
71 {
72         int len;
73         void *ptr;
74
75         if (use_canon_enc) {
76                 // make sure canon_enc is initialized.
77                 i2d_X509_NAME (name->name, NULL);
78
79                 len = name->name->canon_enclen;
80                 ptr = name->name->canon_enc;
81         } else {
82                 len = (int)name->name->bytes->length;
83                 ptr = name->name->bytes->data;
84         }
85
86         *buffer = OPENSSL_malloc (len);
87         if (!*buffer)
88                 return 0;
89
90         memcpy (*buffer, ptr, len);
91         return len;
92 }
93
94 MONO_API MonoBtlsX509Name *
95 mono_btls_x509_name_from_data (const void *data, int len, int use_canon_enc)
96 {
97         MonoBtlsX509Name *name;
98         uint8_t *buf;
99         const unsigned char *ptr;
100         X509_NAME *ret;
101
102         name = OPENSSL_malloc (sizeof (MonoBtlsX509Name));
103         if (!name)
104                 return NULL;
105
106         memset (name, 0, sizeof(MonoBtlsX509Name));
107         name->owns = 1;
108
109         name->name = X509_NAME_new ();
110         if (!name->name) {
111                 OPENSSL_free (name);
112                 return NULL;
113         }
114
115         if (use_canon_enc) {
116                 CBB cbb, contents;
117                 size_t buf_len;
118
119                 // re-add ASN1 SEQUENCE header.
120                 CBB_init(&cbb, 0);
121                 if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
122                     !CBB_add_bytes(&contents, data, len) ||
123                     !CBB_finish(&cbb, &buf, &buf_len)) {
124                         CBB_cleanup (&cbb);
125                         mono_btls_x509_name_free (name);
126                         return NULL;
127                 }
128
129                 ptr = buf;
130                 len = (int)buf_len;
131         } else {
132                 ptr = data;
133                 buf = NULL;
134         }
135
136         ret = d2i_X509_NAME (&name->name, &ptr, len);
137
138         if (buf)
139                 OPENSSL_free (buf);
140
141         if (ret != name->name) {
142                 mono_btls_x509_name_free (name);
143                 return NULL;
144         }
145
146         return name;
147 }
148
149 MONO_API int
150 mono_btls_x509_name_print_string (MonoBtlsX509Name *name, char *buffer, int size)
151 {
152         *buffer = 0;
153         return X509_NAME_oneline (name->name, buffer, size) != NULL;
154 }
155
156 MONO_API int64_t
157 mono_btls_x509_name_hash (MonoBtlsX509Name *name)
158 {
159         return X509_NAME_hash (name->name);
160 }
161
162 MONO_API int64_t
163 mono_btls_x509_name_hash_old (MonoBtlsX509Name *name)
164 {
165         return X509_NAME_hash_old (name->name);
166 }
167
168 MONO_API int
169 mono_btls_x509_name_get_entry_count (MonoBtlsX509Name *name)
170 {
171         return X509_NAME_entry_count (name->name);
172 }
173
174 static MonoBtlsX509NameEntryType
175 nid2mono (int nid)
176 {
177         switch (nid) {
178         case NID_countryName:
179                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_COUNTRY_NAME;
180         case NID_organizationName:
181                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_ORGANIZATION_NAME;
182         case NID_organizationalUnitName:
183                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_ORGANIZATIONAL_UNIT_NAME;
184         case NID_commonName:
185                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_COMMON_NAME;
186         case NID_localityName:
187                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_LOCALITY_NAME;
188         case NID_stateOrProvinceName:
189                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_STATE_OR_PROVINCE_NAME;
190         case NID_streetAddress:
191                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_STREET_ADDRESS;
192         case NID_serialNumber:
193                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_SERIAL_NUMBER;
194         case NID_domainComponent:
195                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_DOMAIN_COMPONENT;
196         case NID_userId:
197                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_USER_ID;
198         case NID_dnQualifier:
199                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_DN_QUALIFIER;
200         case NID_title:
201                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_TITLE;
202         case NID_surname:
203                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_SURNAME;
204         case NID_givenName:
205                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_GIVEN_NAME;
206         case NID_initials:
207                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_INITIAL;
208         default:
209                 return MONO_BTLS_X509_NAME_ENTRY_TYPE_UNKNOWN;
210         }
211 }
212
213 MONO_API MonoBtlsX509NameEntryType
214 mono_btls_x509_name_get_entry_type (MonoBtlsX509Name *name, int index)
215 {
216         X509_NAME_ENTRY *entry;
217         ASN1_OBJECT *obj;
218
219         if (index >= X509_NAME_entry_count (name->name))
220                 return -1;
221
222         entry = X509_NAME_get_entry (name->name, index);
223         if (!entry)
224                 return -1;
225
226         obj = X509_NAME_ENTRY_get_object (entry);
227         if (!obj)
228                 return -1;
229
230         return nid2mono (OBJ_obj2nid (obj));
231 }
232
233 MONO_API int
234 mono_btls_x509_name_get_entry_oid (MonoBtlsX509Name *name, int index, char *buffer, int size)
235 {
236         X509_NAME_ENTRY *entry;
237         ASN1_OBJECT *obj;
238
239         if (index >= X509_NAME_entry_count (name->name))
240                 return 0;
241
242         entry = X509_NAME_get_entry (name->name, index);
243         if (!entry)
244                 return 0;
245
246         obj = X509_NAME_ENTRY_get_object (entry);
247         if (!obj)
248                 return 0;
249
250         return OBJ_obj2txt (buffer, size, obj, 1);
251 }
252
253 MONO_API int
254 mono_btls_x509_name_get_entry_oid_data (MonoBtlsX509Name *name, int index, const void **data)
255 {
256         X509_NAME_ENTRY *entry;
257         ASN1_OBJECT *obj;
258
259         if (index >= X509_NAME_entry_count (name->name))
260                 return -1;
261
262         entry = X509_NAME_get_entry (name->name, index);
263         if (!entry)
264                 return -1;
265
266         obj = X509_NAME_ENTRY_get_object (entry);
267         if (!obj)
268                 return -1;
269
270         *data = obj->data;
271         return obj->length;
272 }
273
274 MONO_API int
275 mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, int *tag, unsigned char **str)
276 {
277         X509_NAME_ENTRY *entry;
278         ASN1_STRING *data;
279
280         *str = NULL;
281         *tag = 0;
282
283         if (index >= X509_NAME_entry_count (name->name))
284                 return 0;
285
286         entry = X509_NAME_get_entry (name->name, index);
287         if (!entry)
288                 return 0;
289
290         data = X509_NAME_ENTRY_get_data (entry);
291         if (!data)
292                 return 0;
293
294         *tag = data->type;
295         return ASN1_STRING_to_UTF8 (str, data);
296 }