]>
Commit | Line | Data |
---|---|---|
62867571 | 1 | /* |
fecb3aae | 2 | * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. |
d02b48c6 | 3 | * |
3f870de7 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
62867571 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
25f2138b | 11 | #include "crypto/ctype.h" |
452ae49d | 12 | #include <limits.h> |
b39fc560 | 13 | #include "internal/cryptlib.h" |
397065c6 | 14 | #include "internal/thread_once.h" |
29c80c60 | 15 | #include "internal/tsan_assist.h" |
ec577822 BM |
16 | #include <openssl/lhash.h> |
17 | #include <openssl/asn1.h> | |
25f2138b | 18 | #include "crypto/objects.h" |
1e26a8ba | 19 | #include <openssl/bn.h> |
25f2138b | 20 | #include "crypto/asn1.h" |
706457b7 | 21 | #include "obj_local.h" |
d02b48c6 | 22 | |
d040a1b9 | 23 | /* obj_dat.h is generated from objects.txt and obj_mac.{num,h} by obj_dat.pl */ |
a00ae6c4 | 24 | #include "obj_dat.h" |
d02b48c6 | 25 | |
e19106f5 DSH |
26 | DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn); |
27 | DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln); | |
28 | DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj); | |
babb3798 | 29 | |
0f113f3e MC |
30 | #define ADDED_DATA 0 |
31 | #define ADDED_SNAME 1 | |
32 | #define ADDED_LNAME 2 | |
33 | #define ADDED_NID 3 | |
d02b48c6 | 34 | |
e6b5c341 | 35 | struct added_obj_st { |
0f113f3e MC |
36 | int type; |
37 | ASN1_OBJECT *obj; | |
e6b5c341 | 38 | }; |
d02b48c6 | 39 | |
0f113f3e | 40 | static LHASH_OF(ADDED_OBJ) *added = NULL; |
397065c6 | 41 | static CRYPTO_RWLOCK *ossl_obj_lock = NULL; |
e6b8f359 | 42 | #ifdef TSAN_REQUIRES_LOCKING |
29c80c60 P |
43 | static CRYPTO_RWLOCK *ossl_obj_nid_lock = NULL; |
44 | #endif | |
397065c6 P |
45 | |
46 | static CRYPTO_ONCE ossl_obj_lock_init = CRYPTO_ONCE_STATIC_INIT; | |
47 | ||
29c80c60 P |
48 | static ossl_inline void objs_free_locks(void) |
49 | { | |
50 | CRYPTO_THREAD_lock_free(ossl_obj_lock); | |
51 | ossl_obj_lock = NULL; | |
e6b8f359 | 52 | #ifdef TSAN_REQUIRES_LOCKING |
29c80c60 P |
53 | CRYPTO_THREAD_lock_free(ossl_obj_nid_lock); |
54 | ossl_obj_nid_lock = NULL; | |
55 | #endif | |
56 | } | |
57 | ||
397065c6 P |
58 | DEFINE_RUN_ONCE_STATIC(obj_lock_initialise) |
59 | { | |
60 | /* Make sure we've loaded config before checking for any "added" objects */ | |
61 | OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); | |
62 | ||
63 | ossl_obj_lock = CRYPTO_THREAD_lock_new(); | |
29c80c60 P |
64 | if (ossl_obj_lock == NULL) |
65 | return 0; | |
66 | ||
e6b8f359 | 67 | #ifdef TSAN_REQUIRES_LOCKING |
29c80c60 P |
68 | ossl_obj_nid_lock = CRYPTO_THREAD_lock_new(); |
69 | if (ossl_obj_nid_lock == NULL) { | |
70 | objs_free_locks(); | |
71 | return 0; | |
72 | } | |
73 | #endif | |
74 | return 1; | |
397065c6 P |
75 | } |
76 | ||
77 | static ossl_inline int ossl_init_added_lock(void) | |
78 | { | |
79 | return RUN_ONCE(&ossl_obj_lock_init, obj_lock_initialise); | |
80 | } | |
81 | ||
82 | static ossl_inline int ossl_obj_write_lock(int lock) | |
83 | { | |
29c80c60 P |
84 | if (!lock) |
85 | return 1; | |
397065c6 P |
86 | if (!ossl_init_added_lock()) |
87 | return 0; | |
29c80c60 | 88 | return CRYPTO_THREAD_write_lock(ossl_obj_lock); |
397065c6 P |
89 | } |
90 | ||
91 | static ossl_inline int ossl_obj_read_lock(int lock) | |
92 | { | |
29c80c60 P |
93 | if (!lock) |
94 | return 1; | |
397065c6 P |
95 | if (!ossl_init_added_lock()) |
96 | return 0; | |
29c80c60 | 97 | return CRYPTO_THREAD_read_lock(ossl_obj_lock); |
397065c6 P |
98 | } |
99 | ||
100 | static ossl_inline void ossl_obj_unlock(int lock) | |
101 | { | |
102 | if (lock) | |
103 | CRYPTO_THREAD_unlock(ossl_obj_lock); | |
104 | } | |
d02b48c6 | 105 | |
0f113f3e MC |
106 | static int sn_cmp(const ASN1_OBJECT *const *a, const unsigned int *b) |
107 | { | |
a2371fa9 | 108 | return strcmp((*a)->sn, nid_objs[*b].sn); |
0f113f3e | 109 | } |
d02b48c6 | 110 | |
e19106f5 | 111 | IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn); |
babb3798 | 112 | |
0f113f3e MC |
113 | static int ln_cmp(const ASN1_OBJECT *const *a, const unsigned int *b) |
114 | { | |
a2371fa9 | 115 | return strcmp((*a)->ln, nid_objs[*b].ln); |
0f113f3e | 116 | } |
babb3798 | 117 | |
e19106f5 | 118 | IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln); |
d02b48c6 | 119 | |
3c1d6bbc | 120 | static unsigned long added_obj_hash(const ADDED_OBJ *ca) |
0f113f3e MC |
121 | { |
122 | const ASN1_OBJECT *a; | |
123 | int i; | |
124 | unsigned long ret = 0; | |
125 | unsigned char *p; | |
126 | ||
127 | a = ca->obj; | |
128 | switch (ca->type) { | |
129 | case ADDED_DATA: | |
130 | ret = a->length << 20L; | |
131 | p = (unsigned char *)a->data; | |
132 | for (i = 0; i < a->length; i++) | |
133 | ret ^= p[i] << ((i * 3) % 24); | |
134 | break; | |
135 | case ADDED_SNAME: | |
739a1eb1 | 136 | ret = OPENSSL_LH_strhash(a->sn); |
0f113f3e MC |
137 | break; |
138 | case ADDED_LNAME: | |
739a1eb1 | 139 | ret = OPENSSL_LH_strhash(a->ln); |
0f113f3e MC |
140 | break; |
141 | case ADDED_NID: | |
142 | ret = a->nid; | |
143 | break; | |
144 | default: | |
145 | /* abort(); */ | |
146 | return 0; | |
147 | } | |
148 | ret &= 0x3fffffffL; | |
149 | ret |= ((unsigned long)ca->type) << 30L; | |
a2371fa9 | 150 | return ret; |
0f113f3e MC |
151 | } |
152 | ||
3c1d6bbc | 153 | static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb) |
0f113f3e MC |
154 | { |
155 | ASN1_OBJECT *a, *b; | |
156 | int i; | |
157 | ||
158 | i = ca->type - cb->type; | |
159 | if (i) | |
a2371fa9 | 160 | return i; |
0f113f3e MC |
161 | a = ca->obj; |
162 | b = cb->obj; | |
163 | switch (ca->type) { | |
164 | case ADDED_DATA: | |
165 | i = (a->length - b->length); | |
166 | if (i) | |
a2371fa9 P |
167 | return i; |
168 | return memcmp(a->data, b->data, (size_t)a->length); | |
0f113f3e MC |
169 | case ADDED_SNAME: |
170 | if (a->sn == NULL) | |
a2371fa9 | 171 | return -1; |
0f113f3e | 172 | else if (b->sn == NULL) |
a2371fa9 | 173 | return 1; |
0f113f3e | 174 | else |
a2371fa9 | 175 | return strcmp(a->sn, b->sn); |
0f113f3e MC |
176 | case ADDED_LNAME: |
177 | if (a->ln == NULL) | |
a2371fa9 | 178 | return -1; |
0f113f3e | 179 | else if (b->ln == NULL) |
a2371fa9 | 180 | return 1; |
0f113f3e | 181 | else |
a2371fa9 | 182 | return strcmp(a->ln, b->ln); |
0f113f3e | 183 | case ADDED_NID: |
a2371fa9 | 184 | return a->nid - b->nid; |
0f113f3e MC |
185 | default: |
186 | /* abort(); */ | |
187 | return 0; | |
188 | } | |
189 | } | |
190 | ||
3c1d6bbc | 191 | static void cleanup1_doall(ADDED_OBJ *a) |
0f113f3e MC |
192 | { |
193 | a->obj->nid = 0; | |
194 | a->obj->flags |= ASN1_OBJECT_FLAG_DYNAMIC | | |
195 | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | ASN1_OBJECT_FLAG_DYNAMIC_DATA; | |
196 | } | |
d02b48c6 | 197 | |
3c1d6bbc | 198 | static void cleanup2_doall(ADDED_OBJ *a) |
0f113f3e MC |
199 | { |
200 | a->obj->nid++; | |
201 | } | |
d02b48c6 | 202 | |
3c1d6bbc | 203 | static void cleanup3_doall(ADDED_OBJ *a) |
0f113f3e MC |
204 | { |
205 | if (--a->obj->nid == 0) | |
206 | ASN1_OBJECT_free(a->obj); | |
207 | OPENSSL_free(a); | |
208 | } | |
d02b48c6 | 209 | |
f148f703 | 210 | void ossl_obj_cleanup_int(void) |
0f113f3e | 211 | { |
397065c6 P |
212 | if (added != NULL) { |
213 | lh_ADDED_OBJ_set_down_load(added, 0); | |
214 | lh_ADDED_OBJ_doall(added, cleanup1_doall); /* zero counters */ | |
215 | lh_ADDED_OBJ_doall(added, cleanup2_doall); /* set counters */ | |
216 | lh_ADDED_OBJ_doall(added, cleanup3_doall); /* free objects */ | |
217 | lh_ADDED_OBJ_free(added); | |
218 | added = NULL; | |
219 | } | |
29c80c60 | 220 | objs_free_locks(); |
0f113f3e | 221 | } |
d02b48c6 | 222 | |
29c80c60 | 223 | int OBJ_new_nid(int num) |
0f113f3e | 224 | { |
e6b8f359 P |
225 | static TSAN_QUALIFIER int new_nid = NUM_NID; |
226 | #ifdef TSAN_REQUIRES_LOCKING | |
0f113f3e | 227 | int i; |
d02b48c6 | 228 | |
397065c6 P |
229 | if (!CRYPTO_THREAD_write_lock(ossl_obj_nid_lock)) { |
230 | ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK); | |
231 | return NID_undef; | |
232 | } | |
0f113f3e MC |
233 | i = new_nid; |
234 | new_nid += num; | |
29c80c60 | 235 | CRYPTO_THREAD_unlock(ossl_obj_nid_lock); |
a2371fa9 | 236 | return i; |
29c80c60 | 237 | #else |
29c80c60 P |
238 | return tsan_add(&new_nid, num); |
239 | #endif | |
0f113f3e | 240 | } |
d02b48c6 | 241 | |
397065c6 | 242 | static int ossl_obj_add_object(const ASN1_OBJECT *obj, int lock) |
0f113f3e | 243 | { |
397065c6 | 244 | ASN1_OBJECT *o = NULL; |
0f113f3e MC |
245 | ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop; |
246 | int i; | |
247 | ||
0f113f3e | 248 | if ((o = OBJ_dup(obj)) == NULL) |
397065c6 P |
249 | return NID_undef; |
250 | if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL | |
251 | || (o->length != 0 | |
252 | && obj->data != NULL | |
253 | && (ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) | |
254 | || (o->sn != NULL | |
255 | && (ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) | |
256 | || (o->ln != NULL | |
e077455e | 257 | && (ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)) |
397065c6 | 258 | goto err2; |
397065c6 P |
259 | |
260 | if (!ossl_obj_write_lock(lock)) { | |
261 | ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK); | |
0f113f3e | 262 | goto err2; |
397065c6 P |
263 | } |
264 | if (added == NULL) { | |
265 | added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp); | |
266 | if (added == NULL) { | |
e077455e | 267 | ERR_raise(ERR_LIB_OBJ, ERR_R_CRYPTO_LIB); |
397065c6 P |
268 | goto err; |
269 | } | |
270 | } | |
0f113f3e MC |
271 | |
272 | for (i = ADDED_DATA; i <= ADDED_NID; i++) { | |
273 | if (ao[i] != NULL) { | |
274 | ao[i]->type = i; | |
275 | ao[i]->obj = o; | |
276 | aop = lh_ADDED_OBJ_insert(added, ao[i]); | |
f430ba31 | 277 | /* memory leak, but should not normally matter */ |
b548a1f1 | 278 | OPENSSL_free(aop); |
0f113f3e MC |
279 | } |
280 | } | |
281 | o->flags &= | |
282 | ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | | |
283 | ASN1_OBJECT_FLAG_DYNAMIC_DATA); | |
284 | ||
397065c6 | 285 | ossl_obj_unlock(lock); |
a2371fa9 | 286 | return o->nid; |
397065c6 | 287 | |
0f113f3e | 288 | err: |
397065c6 P |
289 | ossl_obj_unlock(lock); |
290 | err2: | |
0f113f3e | 291 | for (i = ADDED_DATA; i <= ADDED_NID; i++) |
b548a1f1 | 292 | OPENSSL_free(ao[i]); |
c130c0fe | 293 | ASN1_OBJECT_free(o); |
a2371fa9 | 294 | return NID_undef; |
0f113f3e | 295 | } |
d02b48c6 | 296 | |
6b691a5c | 297 | ASN1_OBJECT *OBJ_nid2obj(int n) |
0f113f3e | 298 | { |
397065c6 | 299 | ADDED_OBJ ad, *adp = NULL; |
0f113f3e MC |
300 | ASN1_OBJECT ob; |
301 | ||
908ba3ed TM |
302 | if (n == NID_undef |
303 | || (n > 0 && n < NUM_NID && nid_objs[n].nid != NID_undef)) | |
67890a73 | 304 | return (ASN1_OBJECT *)&(nid_objs[n]); |
29dc6e00 MC |
305 | |
306 | ad.type = ADDED_NID; | |
307 | ad.obj = &ob; | |
308 | ob.nid = n; | |
397065c6 P |
309 | if (!ossl_obj_read_lock(1)) { |
310 | ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); | |
311 | return NULL; | |
312 | } | |
313 | if (added != NULL) | |
314 | adp = lh_ADDED_OBJ_retrieve(added, &ad); | |
315 | ossl_obj_unlock(1); | |
29dc6e00 MC |
316 | if (adp != NULL) |
317 | return adp->obj; | |
318 | ||
9311d0c4 | 319 | ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID); |
29dc6e00 | 320 | return NULL; |
0f113f3e | 321 | } |
d02b48c6 | 322 | |
6b691a5c | 323 | const char *OBJ_nid2sn(int n) |
0f113f3e | 324 | { |
397065c6 | 325 | ASN1_OBJECT *ob = OBJ_nid2obj(n); |
29dc6e00 | 326 | |
397065c6 | 327 | return ob == NULL ? NULL : ob->sn; |
0f113f3e | 328 | } |
d02b48c6 | 329 | |
6b691a5c | 330 | const char *OBJ_nid2ln(int n) |
0f113f3e | 331 | { |
397065c6 | 332 | ASN1_OBJECT *ob = OBJ_nid2obj(n); |
29dc6e00 | 333 | |
397065c6 | 334 | return ob == NULL ? NULL : ob->ln; |
0f113f3e MC |
335 | } |
336 | ||
337 | static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp) | |
338 | { | |
339 | int j; | |
340 | const ASN1_OBJECT *a = *ap; | |
341 | const ASN1_OBJECT *b = &nid_objs[*bp]; | |
342 | ||
343 | j = (a->length - b->length); | |
344 | if (j) | |
a2371fa9 | 345 | return j; |
2b8dc08b HB |
346 | if (a->length == 0) |
347 | return 0; | |
a2371fa9 | 348 | return memcmp(a->data, b->data, a->length); |
0f113f3e | 349 | } |
babb3798 | 350 | |
e19106f5 | 351 | IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj); |
babb3798 | 352 | |
397065c6 | 353 | static int ossl_obj_obj2nid(const ASN1_OBJECT *a, const int lock) |
0f113f3e | 354 | { |
397065c6 | 355 | int nid = NID_undef; |
0f113f3e MC |
356 | const unsigned int *op; |
357 | ADDED_OBJ ad, *adp; | |
358 | ||
359 | if (a == NULL) | |
a2371fa9 | 360 | return NID_undef; |
397065c6 | 361 | if (a->nid != NID_undef) |
a2371fa9 | 362 | return a->nid; |
0fb99904 DSH |
363 | if (a->length == 0) |
364 | return NID_undef; | |
365 | ||
397065c6 P |
366 | op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ); |
367 | if (op != NULL) | |
368 | return nid_objs[*op].nid; | |
369 | if (!ossl_obj_read_lock(lock)) { | |
370 | ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); | |
371 | return NID_undef; | |
372 | } | |
0f113f3e MC |
373 | if (added != NULL) { |
374 | ad.type = ADDED_DATA; | |
397065c6 | 375 | ad.obj = (ASN1_OBJECT *)a; /* casting away const is harmless here */ |
0f113f3e MC |
376 | adp = lh_ADDED_OBJ_retrieve(added, &ad); |
377 | if (adp != NULL) | |
397065c6 | 378 | nid = adp->obj->nid; |
0f113f3e | 379 | } |
397065c6 P |
380 | ossl_obj_unlock(lock); |
381 | return nid; | |
0f113f3e MC |
382 | } |
383 | ||
384 | /* | |
385 | * Convert an object name into an ASN1_OBJECT if "noname" is not set then | |
386 | * search for short and long names first. This will convert the "dotted" form | |
387 | * into an object: unlike OBJ_txt2nid it can be used with any objects, not | |
388 | * just registered ones. | |
2d723902 | 389 | */ |
6b691a5c | 390 | ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) |
0f113f3e MC |
391 | { |
392 | int nid = NID_undef; | |
397065c6 | 393 | ASN1_OBJECT *op = NULL; |
0f113f3e MC |
394 | unsigned char *buf; |
395 | unsigned char *p; | |
396 | const unsigned char *cp; | |
397 | int i, j; | |
398 | ||
399 | if (!no_name) { | |
67890a73 DDO |
400 | if ((nid = OBJ_sn2nid(s)) != NID_undef |
401 | || (nid = OBJ_ln2nid(s)) != NID_undef) { | |
0f113f3e | 402 | return OBJ_nid2obj(nid); |
397065c6 | 403 | } |
b516a4b1 | 404 | if (!ossl_isdigit(*s)) { |
9311d0c4 | 405 | ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_OBJECT_NAME); |
b516a4b1 DDO |
406 | return NULL; |
407 | } | |
0f113f3e MC |
408 | } |
409 | ||
410 | /* Work out size of content octets */ | |
411 | i = a2d_ASN1_OBJECT(NULL, 0, s, -1); | |
397065c6 | 412 | if (i <= 0) |
0f113f3e | 413 | return NULL; |
397065c6 | 414 | |
0f113f3e MC |
415 | /* Work out total size */ |
416 | j = ASN1_object_size(0, i, V_ASN1_OBJECT); | |
a36c5eab MC |
417 | if (j < 0) |
418 | return NULL; | |
0f113f3e | 419 | |
e077455e | 420 | if ((buf = OPENSSL_malloc(j)) == NULL) |
0f113f3e MC |
421 | return NULL; |
422 | ||
423 | p = buf; | |
424 | /* Write out tag+length */ | |
425 | ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); | |
426 | /* Write out contents */ | |
427 | a2d_ASN1_OBJECT(p, i, s, -1); | |
428 | ||
429 | cp = buf; | |
430 | op = d2i_ASN1_OBJECT(NULL, &cp, j); | |
431 | OPENSSL_free(buf); | |
432 | return op; | |
433 | } | |
d02b48c6 | 434 | |
6343829a | 435 | int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) |
3e3d2ea2 | 436 | { |
0f113f3e MC |
437 | int i, n = 0, len, nid, first, use_bn; |
438 | BIGNUM *bl; | |
439 | unsigned long l; | |
440 | const unsigned char *p; | |
441 | char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2]; | |
397065c6 | 442 | const char *s; |
0f113f3e MC |
443 | |
444 | /* Ensure that, at every state, |buf| is NUL-terminated. */ | |
397065c6 | 445 | if (buf != NULL && buf_len > 0) |
0f113f3e MC |
446 | buf[0] = '\0'; |
447 | ||
397065c6 | 448 | if (a == NULL || a->data == NULL) |
a2371fa9 | 449 | return 0; |
0f113f3e MC |
450 | |
451 | if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) { | |
0f113f3e MC |
452 | s = OBJ_nid2ln(nid); |
453 | if (s == NULL) | |
454 | s = OBJ_nid2sn(nid); | |
397065c6 P |
455 | if (s != NULL) { |
456 | if (buf != NULL) | |
7644a9ae | 457 | OPENSSL_strlcpy(buf, s, buf_len); |
397065c6 | 458 | return (int)strlen(s); |
0f113f3e MC |
459 | } |
460 | } | |
461 | ||
462 | len = a->length; | |
463 | p = a->data; | |
464 | ||
465 | first = 1; | |
466 | bl = NULL; | |
467 | ||
468 | while (len > 0) { | |
469 | l = 0; | |
470 | use_bn = 0; | |
471 | for (;;) { | |
472 | unsigned char c = *p++; | |
67890a73 | 473 | |
0f113f3e | 474 | len--; |
67890a73 | 475 | if (len == 0 && (c & 0x80) != 0) |
0f113f3e MC |
476 | goto err; |
477 | if (use_bn) { | |
478 | if (!BN_add_word(bl, c & 0x7f)) | |
479 | goto err; | |
67890a73 | 480 | } else { |
0f113f3e | 481 | l |= c & 0x7f; |
67890a73 DDO |
482 | } |
483 | if ((c & 0x80) == 0) | |
0f113f3e | 484 | break; |
67890a73 | 485 | if (!use_bn && l > (ULONG_MAX >> 7L)) { |
75ebbd9a | 486 | if (bl == NULL && (bl = BN_new()) == NULL) |
0f113f3e MC |
487 | goto err; |
488 | if (!BN_set_word(bl, l)) | |
489 | goto err; | |
490 | use_bn = 1; | |
491 | } | |
492 | if (use_bn) { | |
493 | if (!BN_lshift(bl, bl, 7)) | |
494 | goto err; | |
67890a73 | 495 | } else { |
0f113f3e | 496 | l <<= 7L; |
67890a73 | 497 | } |
0f113f3e MC |
498 | } |
499 | ||
500 | if (first) { | |
501 | first = 0; | |
502 | if (l >= 80) { | |
503 | i = 2; | |
504 | if (use_bn) { | |
505 | if (!BN_sub_word(bl, 80)) | |
506 | goto err; | |
67890a73 | 507 | } else { |
0f113f3e | 508 | l -= 80; |
67890a73 | 509 | } |
0f113f3e MC |
510 | } else { |
511 | i = (int)(l / 40); | |
512 | l -= (long)(i * 40); | |
513 | } | |
67890a73 | 514 | if (buf != NULL && buf_len > 1) { |
0f113f3e MC |
515 | *buf++ = i + '0'; |
516 | *buf = '\0'; | |
517 | buf_len--; | |
518 | } | |
519 | n++; | |
520 | } | |
521 | ||
522 | if (use_bn) { | |
523 | char *bndec; | |
524 | bndec = BN_bn2dec(bl); | |
525 | if (!bndec) | |
526 | goto err; | |
527 | i = strlen(bndec); | |
67890a73 | 528 | if (buf != NULL) { |
0f113f3e MC |
529 | if (buf_len > 1) { |
530 | *buf++ = '.'; | |
531 | *buf = '\0'; | |
532 | buf_len--; | |
533 | } | |
7644a9ae | 534 | OPENSSL_strlcpy(buf, bndec, buf_len); |
0f113f3e MC |
535 | if (i > buf_len) { |
536 | buf += buf_len; | |
537 | buf_len = 0; | |
538 | } else { | |
539 | buf += i; | |
540 | buf_len -= i; | |
541 | } | |
542 | } | |
543 | n++; | |
544 | n += i; | |
545 | OPENSSL_free(bndec); | |
546 | } else { | |
a2371fa9 | 547 | BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l); |
0f113f3e | 548 | i = strlen(tbuf); |
67890a73 | 549 | if (buf && buf_len > 0) { |
7644a9ae | 550 | OPENSSL_strlcpy(buf, tbuf, buf_len); |
0f113f3e MC |
551 | if (i > buf_len) { |
552 | buf += buf_len; | |
553 | buf_len = 0; | |
554 | } else { | |
555 | buf += i; | |
556 | buf_len -= i; | |
557 | } | |
558 | } | |
559 | n += i; | |
560 | l = 0; | |
561 | } | |
562 | } | |
563 | ||
23a1d5e9 | 564 | BN_free(bl); |
0f113f3e MC |
565 | return n; |
566 | ||
567 | err: | |
23a1d5e9 | 568 | BN_free(bl); |
0f113f3e | 569 | return -1; |
3e3d2ea2 DSH |
570 | } |
571 | ||
8d28d5f8 | 572 | int OBJ_txt2nid(const char *s) |
2d723902 | 573 | { |
397065c6 P |
574 | ASN1_OBJECT *obj = OBJ_txt2obj(s, 0); |
575 | int nid = NID_undef; | |
576 | ||
577 | if (obj != NULL) { | |
578 | nid = OBJ_obj2nid(obj); | |
579 | ASN1_OBJECT_free(obj); | |
580 | } | |
0f113f3e | 581 | return nid; |
2d723902 DSH |
582 | } |
583 | ||
6b691a5c | 584 | int OBJ_ln2nid(const char *s) |
0f113f3e MC |
585 | { |
586 | ASN1_OBJECT o; | |
587 | const ASN1_OBJECT *oo = &o; | |
588 | ADDED_OBJ ad, *adp; | |
589 | const unsigned int *op; | |
397065c6 | 590 | int nid = NID_undef; |
29dc6e00 | 591 | |
0f113f3e | 592 | o.ln = s; |
397065c6 P |
593 | op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN); |
594 | if (op != NULL) | |
595 | return nid_objs[*op].nid; | |
596 | if (!ossl_obj_read_lock(1)) { | |
597 | ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); | |
598 | return NID_undef; | |
599 | } | |
0f113f3e MC |
600 | if (added != NULL) { |
601 | ad.type = ADDED_LNAME; | |
602 | ad.obj = &o; | |
603 | adp = lh_ADDED_OBJ_retrieve(added, &ad); | |
604 | if (adp != NULL) | |
397065c6 | 605 | nid = adp->obj->nid; |
0f113f3e | 606 | } |
397065c6 P |
607 | ossl_obj_unlock(1); |
608 | return nid; | |
0f113f3e | 609 | } |
d02b48c6 | 610 | |
6b691a5c | 611 | int OBJ_sn2nid(const char *s) |
0f113f3e MC |
612 | { |
613 | ASN1_OBJECT o; | |
614 | const ASN1_OBJECT *oo = &o; | |
615 | ADDED_OBJ ad, *adp; | |
616 | const unsigned int *op; | |
397065c6 | 617 | int nid = NID_undef; |
29dc6e00 | 618 | |
0f113f3e | 619 | o.sn = s; |
397065c6 P |
620 | op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN); |
621 | if (op != NULL) | |
622 | return nid_objs[*op].nid; | |
623 | if (!ossl_obj_read_lock(1)) { | |
624 | ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); | |
625 | return NID_undef; | |
626 | } | |
0f113f3e MC |
627 | if (added != NULL) { |
628 | ad.type = ADDED_SNAME; | |
629 | ad.obj = &o; | |
630 | adp = lh_ADDED_OBJ_retrieve(added, &ad); | |
631 | if (adp != NULL) | |
397065c6 | 632 | nid = adp->obj->nid; |
0f113f3e | 633 | } |
397065c6 P |
634 | ossl_obj_unlock(1); |
635 | return nid; | |
0f113f3e | 636 | } |
d02b48c6 | 637 | |
babb3798 | 638 | const void *OBJ_bsearch_(const void *key, const void *base, int num, int size, |
0f113f3e MC |
639 | int (*cmp) (const void *, const void *)) |
640 | { | |
641 | return OBJ_bsearch_ex_(key, base, num, size, cmp, 0); | |
642 | } | |
ea5240a5 | 643 | |
5c3f1e34 | 644 | const void *OBJ_bsearch_ex_(const void *key, const void *base, int num, |
0f113f3e MC |
645 | int size, |
646 | int (*cmp) (const void *, const void *), | |
647 | int flags) | |
648 | { | |
5c3f1e34 | 649 | const char *p = ossl_bsearch(key, base, num, size, cmp, flags); |
0f113f3e | 650 | |
a53955d8 | 651 | #ifdef CHARSET_EBCDIC |
0f113f3e MC |
652 | /* |
653 | * THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I | |
654 | * don't have perl (yet), we revert to a *LINEAR* search when the object | |
655 | * wasn't found in the binary search. | |
656 | */ | |
5c3f1e34 RL |
657 | if (p == NULL) { |
658 | const char *base_ = base; | |
659 | int l, h, i = 0, c = 0; | |
660 | ||
0f113f3e | 661 | for (i = 0; i < num; ++i) { |
5c3f1e34 | 662 | p = &(base_[i * size]); |
0f113f3e | 663 | c = (*cmp) (key, p); |
5c3f1e34 RL |
664 | if (c == 0 |
665 | || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))) | |
0f113f3e MC |
666 | return p; |
667 | } | |
668 | } | |
a53955d8 | 669 | #endif |
a2371fa9 | 670 | return p; |
0f113f3e | 671 | } |
d02b48c6 | 672 | |
cef115ff F |
673 | /* |
674 | * Parse a BIO sink to create some extra oid's objects. | |
675 | * Line format:<OID:isdigit or '.']><isspace><SN><isspace><LN> | |
676 | */ | |
6b691a5c | 677 | int OBJ_create_objects(BIO *in) |
0f113f3e | 678 | { |
68b00c23 | 679 | char buf[512]; |
0f113f3e MC |
680 | int i, num = 0; |
681 | char *o, *s, *l = NULL; | |
682 | ||
683 | for (;;) { | |
684 | s = o = NULL; | |
685 | i = BIO_gets(in, buf, 512); | |
686 | if (i <= 0) | |
a2371fa9 | 687 | return num; |
0f113f3e | 688 | buf[i - 1] = '\0'; |
a1df06b3 | 689 | if (!ossl_isalnum(buf[0])) |
a2371fa9 | 690 | return num; |
0f113f3e | 691 | o = s = buf; |
a1df06b3 | 692 | while (ossl_isdigit(*s) || *s == '.') |
0f113f3e MC |
693 | s++; |
694 | if (*s != '\0') { | |
695 | *(s++) = '\0'; | |
a1df06b3 | 696 | while (ossl_isspace(*s)) |
0f113f3e | 697 | s++; |
cef115ff | 698 | if (*s == '\0') { |
0f113f3e | 699 | s = NULL; |
cef115ff | 700 | } else { |
0f113f3e | 701 | l = s; |
a1df06b3 | 702 | while (*l != '\0' && !ossl_isspace(*l)) |
0f113f3e MC |
703 | l++; |
704 | if (*l != '\0') { | |
705 | *(l++) = '\0'; | |
a1df06b3 | 706 | while (ossl_isspace(*l)) |
0f113f3e | 707 | l++; |
cef115ff | 708 | if (*l == '\0') { |
0f113f3e | 709 | l = NULL; |
cef115ff F |
710 | } |
711 | } else { | |
0f113f3e | 712 | l = NULL; |
cef115ff | 713 | } |
0f113f3e | 714 | } |
cef115ff | 715 | } else { |
0f113f3e | 716 | s = NULL; |
cef115ff F |
717 | } |
718 | if (*o == '\0') | |
a2371fa9 | 719 | return num; |
0f113f3e | 720 | if (!OBJ_create(o, s, l)) |
a2371fa9 | 721 | return num; |
0f113f3e MC |
722 | num++; |
723 | } | |
0f113f3e | 724 | } |
58964a49 | 725 | |
8d28d5f8 | 726 | int OBJ_create(const char *oid, const char *sn, const char *ln) |
0f113f3e | 727 | { |
52832e47 | 728 | ASN1_OBJECT *tmpoid = NULL; |
e64b5557 | 729 | int ok = 0; |
0f113f3e | 730 | |
b79da97c RL |
731 | /* With no arguments at all, nothing can be done */ |
732 | if (oid == NULL && sn == NULL && ln == NULL) { | |
733 | ERR_raise(ERR_LIB_OBJ, ERR_R_PASSED_INVALID_ARGUMENT); | |
734 | return 0; | |
735 | } | |
736 | ||
52832e47 | 737 | /* Check to see if short or long name already present */ |
f13615c5 MC |
738 | if ((sn != NULL && OBJ_sn2nid(sn) != NID_undef) |
739 | || (ln != NULL && OBJ_ln2nid(ln) != NID_undef)) { | |
9311d0c4 | 740 | ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS); |
10481d33 | 741 | return 0; |
0f113f3e | 742 | } |
52832e47 | 743 | |
b79da97c RL |
744 | if (oid != NULL) { |
745 | /* Convert numerical OID string to an ASN1_OBJECT structure */ | |
746 | tmpoid = OBJ_txt2obj(oid, 1); | |
747 | if (tmpoid == NULL) | |
748 | return 0; | |
749 | } else { | |
750 | /* Create a no-OID ASN1_OBJECT */ | |
751 | tmpoid = ASN1_OBJECT_new(); | |
752 | } | |
397065c6 P |
753 | |
754 | if (!ossl_obj_write_lock(1)) { | |
755 | ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK); | |
10481d33 | 756 | ASN1_OBJECT_free(tmpoid); |
487a73de | 757 | return 0; |
397065c6 | 758 | } |
52832e47 DSH |
759 | |
760 | /* If NID is not NID_undef then object already exists */ | |
b79da97c RL |
761 | if (oid != NULL |
762 | && ossl_obj_obj2nid(tmpoid, 0) != NID_undef) { | |
9311d0c4 | 763 | ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS); |
0f113f3e | 764 | goto err; |
52832e47 DSH |
765 | } |
766 | ||
29c80c60 | 767 | tmpoid->nid = OBJ_new_nid(1); |
a0ff8e41 | 768 | if (tmpoid->nid == NID_undef) |
769 | goto err; | |
770 | ||
52832e47 DSH |
771 | tmpoid->sn = (char *)sn; |
772 | tmpoid->ln = (char *)ln; | |
773 | ||
397065c6 | 774 | ok = ossl_obj_add_object(tmpoid, 0); |
52832e47 DSH |
775 | |
776 | tmpoid->sn = NULL; | |
777 | tmpoid->ln = NULL; | |
778 | ||
0f113f3e | 779 | err: |
397065c6 | 780 | ossl_obj_unlock(1); |
52832e47 DSH |
781 | ASN1_OBJECT_free(tmpoid); |
782 | return ok; | |
0f113f3e | 783 | } |
2e430277 DSH |
784 | |
785 | size_t OBJ_length(const ASN1_OBJECT *obj) | |
786 | { | |
787 | if (obj == NULL) | |
788 | return 0; | |
789 | return obj->length; | |
790 | } | |
791 | ||
792 | const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj) | |
793 | { | |
794 | if (obj == NULL) | |
795 | return NULL; | |
796 | return obj->data; | |
797 | } | |
397065c6 | 798 | |
397065c6 P |
799 | int OBJ_add_object(const ASN1_OBJECT *obj) |
800 | { | |
801 | return ossl_obj_add_object(obj, 1); | |
802 | } | |
803 | ||
804 | int OBJ_obj2nid(const ASN1_OBJECT *a) | |
805 | { | |
806 | return ossl_obj_obj2nid(a, 1); | |
807 | } |