Fix potential crash for Encoder.Convert (#20522)
[mono-project.git] / mono / btls / btls-x509-name.c
blob6adce430ca293ee3f62276a657a0d46729164004
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 //
9 #include "btls-x509-name.h"
11 struct MonoBtlsX509Name {
12 int owns;
13 X509_NAME *name;
16 MonoBtlsX509Name *
17 mono_btls_x509_name_from_name (X509_NAME *xn)
19 MonoBtlsX509Name *name;
21 name = OPENSSL_malloc (sizeof (MonoBtlsX509Name));
22 if (!name)
23 return NULL;
25 memset(name, 0, sizeof(MonoBtlsX509Name));
26 name->name = xn;
27 return name;
30 MonoBtlsX509Name *
31 mono_btls_x509_name_copy (X509_NAME *xn)
33 MonoBtlsX509Name *name;
35 name = OPENSSL_malloc (sizeof (MonoBtlsX509Name));
36 if (!name)
37 return NULL;
39 memset(name, 0, sizeof(MonoBtlsX509Name));
40 name->name = X509_NAME_dup(xn);
41 name->owns = 1;
42 return name;
45 void
46 mono_btls_x509_name_free (MonoBtlsX509Name *name)
48 if (name->owns) {
49 if (name->name) {
50 X509_NAME_free(name->name);
51 name->name = NULL;
54 OPENSSL_free(name);
57 X509_NAME *
58 mono_btls_x509_name_peek_name (MonoBtlsX509Name *name)
60 return name->name;
63 int
64 mono_btls_x509_name_print_bio (MonoBtlsX509Name *name, BIO *bio)
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);
69 int
70 mono_btls_x509_name_get_raw_data (MonoBtlsX509Name *name, void **buffer, int use_canon_enc)
72 int len;
73 void *ptr;
75 if (use_canon_enc) {
76 // make sure canon_enc is initialized.
77 i2d_X509_NAME (name->name, NULL);
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;
86 *buffer = OPENSSL_malloc (len);
87 if (!*buffer)
88 return 0;
90 memcpy (*buffer, ptr, len);
91 return len;
94 MonoBtlsX509Name *
95 mono_btls_x509_name_from_data (const void *data, int len, int use_canon_enc)
97 MonoBtlsX509Name *name;
98 uint8_t *buf;
99 const unsigned char *ptr;
100 X509_NAME *ret;
102 name = OPENSSL_malloc (sizeof (MonoBtlsX509Name));
103 if (!name)
104 return NULL;
106 memset (name, 0, sizeof(MonoBtlsX509Name));
107 name->owns = 1;
109 name->name = X509_NAME_new ();
110 if (!name->name) {
111 OPENSSL_free (name);
112 return NULL;
115 if (use_canon_enc) {
116 CBB cbb, contents;
117 size_t buf_len;
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;
129 ptr = buf;
130 len = (int)buf_len;
131 } else {
132 ptr = data;
133 buf = NULL;
136 ret = d2i_X509_NAME (&name->name, &ptr, len);
138 if (buf)
139 OPENSSL_free (buf);
141 if (ret != name->name) {
142 mono_btls_x509_name_free (name);
143 return NULL;
146 return name;
150 mono_btls_x509_name_print_string (MonoBtlsX509Name *name, char *buffer, int size)
152 *buffer = 0;
153 return X509_NAME_oneline (name->name, buffer, size) != NULL;
156 int64_t
157 mono_btls_x509_name_hash (MonoBtlsX509Name *name)
159 return X509_NAME_hash (name->name);
162 int64_t
163 mono_btls_x509_name_hash_old (MonoBtlsX509Name *name)
165 return X509_NAME_hash_old (name->name);
169 mono_btls_x509_name_get_entry_count (MonoBtlsX509Name *name)
171 return X509_NAME_entry_count (name->name);
174 static MonoBtlsX509NameEntryType
175 nid2mono (int nid)
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;
213 MonoBtlsX509NameEntryType
214 mono_btls_x509_name_get_entry_type (MonoBtlsX509Name *name, int index)
216 X509_NAME_ENTRY *entry;
217 ASN1_OBJECT *obj;
219 if (index >= X509_NAME_entry_count (name->name))
220 return -1;
222 entry = X509_NAME_get_entry (name->name, index);
223 if (!entry)
224 return -1;
226 obj = X509_NAME_ENTRY_get_object (entry);
227 if (!obj)
228 return -1;
230 return nid2mono (OBJ_obj2nid (obj));
234 mono_btls_x509_name_get_entry_oid (MonoBtlsX509Name *name, int index, char *buffer, int size)
236 X509_NAME_ENTRY *entry;
237 ASN1_OBJECT *obj;
239 if (index >= X509_NAME_entry_count (name->name))
240 return 0;
242 entry = X509_NAME_get_entry (name->name, index);
243 if (!entry)
244 return 0;
246 obj = X509_NAME_ENTRY_get_object (entry);
247 if (!obj)
248 return 0;
250 return OBJ_obj2txt (buffer, size, obj, 1);
254 mono_btls_x509_name_get_entry_oid_data (MonoBtlsX509Name *name, int index, const void **data)
256 X509_NAME_ENTRY *entry;
257 ASN1_OBJECT *obj;
259 if (index >= X509_NAME_entry_count (name->name))
260 return -1;
262 entry = X509_NAME_get_entry (name->name, index);
263 if (!entry)
264 return -1;
266 obj = X509_NAME_ENTRY_get_object (entry);
267 if (!obj)
268 return -1;
270 *data = obj->data;
271 return obj->length;
275 mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, int *tag, unsigned char **str)
277 X509_NAME_ENTRY *entry;
278 ASN1_STRING *data;
280 *str = NULL;
281 *tag = 0;
283 if (index >= X509_NAME_entry_count (name->name))
284 return 0;
286 entry = X509_NAME_get_entry (name->name, index);
287 if (!entry)
288 return 0;
290 data = X509_NAME_ENTRY_get_data (entry);
291 if (!data)
292 return 0;
294 *tag = data->type;
295 return ASN1_STRING_to_UTF8 (str, data);