diff options
Diffstat (limited to 'src/lib/libcrypto/asn1/x_name.c')
-rw-r--r-- | src/lib/libcrypto/asn1/x_name.c | 298 |
1 files changed, 270 insertions, 28 deletions
diff --git a/src/lib/libcrypto/asn1/x_name.c b/src/lib/libcrypto/asn1/x_name.c index 04380abc3f..caa4409feb 100644 --- a/src/lib/libcrypto/asn1/x_name.c +++ b/src/lib/libcrypto/asn1/x_name.c | |||
@@ -57,18 +57,36 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | #include <stdio.h> | 59 | #include <stdio.h> |
60 | #include <ctype.h> | ||
60 | #include "cryptlib.h" | 61 | #include "cryptlib.h" |
61 | #include <openssl/asn1t.h> | 62 | #include <openssl/asn1t.h> |
62 | #include <openssl/x509.h> | 63 | #include <openssl/x509.h> |
64 | #include "asn1_locl.h" | ||
63 | 65 | ||
64 | static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it, | 66 | typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; |
65 | int tag, int aclass, char opt, ASN1_TLC *ctx); | 67 | DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY) |
66 | 68 | ||
67 | static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); | 69 | static int x509_name_ex_d2i(ASN1_VALUE **val, |
70 | const unsigned char **in, long len, | ||
71 | const ASN1_ITEM *it, | ||
72 | int tag, int aclass, char opt, ASN1_TLC *ctx); | ||
73 | |||
74 | static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, | ||
75 | const ASN1_ITEM *it, int tag, int aclass); | ||
68 | static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); | 76 | static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); |
69 | static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); | 77 | static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); |
70 | 78 | ||
71 | static int x509_name_encode(X509_NAME *a); | 79 | static int x509_name_encode(X509_NAME *a); |
80 | static int x509_name_canon(X509_NAME *a); | ||
81 | static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in); | ||
82 | static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname, | ||
83 | unsigned char **in); | ||
84 | |||
85 | |||
86 | static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, | ||
87 | int indent, | ||
88 | const char *fname, | ||
89 | const ASN1_PCTX *pctx); | ||
72 | 90 | ||
73 | ASN1_SEQUENCE(X509_NAME_ENTRY) = { | 91 | ASN1_SEQUENCE(X509_NAME_ENTRY) = { |
74 | ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), | 92 | ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), |
@@ -102,7 +120,8 @@ const ASN1_EXTERN_FUNCS x509_name_ff = { | |||
102 | x509_name_ex_free, | 120 | x509_name_ex_free, |
103 | 0, /* Default clear behaviour is OK */ | 121 | 0, /* Default clear behaviour is OK */ |
104 | x509_name_ex_d2i, | 122 | x509_name_ex_d2i, |
105 | x509_name_ex_i2d | 123 | x509_name_ex_i2d, |
124 | x509_name_ex_print | ||
106 | }; | 125 | }; |
107 | 126 | ||
108 | IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) | 127 | IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) |
@@ -118,6 +137,8 @@ static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) | |||
118 | if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL) | 137 | if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL) |
119 | goto memerr; | 138 | goto memerr; |
120 | if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr; | 139 | if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr; |
140 | ret->canon_enc = NULL; | ||
141 | ret->canon_enclen = 0; | ||
121 | ret->modified=1; | 142 | ret->modified=1; |
122 | *val = (ASN1_VALUE *)ret; | 143 | *val = (ASN1_VALUE *)ret; |
123 | return 1; | 144 | return 1; |
@@ -142,25 +163,19 @@ static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) | |||
142 | 163 | ||
143 | BUF_MEM_free(a->bytes); | 164 | BUF_MEM_free(a->bytes); |
144 | sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free); | 165 | sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free); |
166 | if (a->canon_enc) | ||
167 | OPENSSL_free(a->canon_enc); | ||
145 | OPENSSL_free(a); | 168 | OPENSSL_free(a); |
146 | *pval = NULL; | 169 | *pval = NULL; |
147 | } | 170 | } |
148 | 171 | ||
149 | /* Used with sk_pop_free() to free up the internal representation. | 172 | static int x509_name_ex_d2i(ASN1_VALUE **val, |
150 | * NB: we only free the STACK and not its contents because it is | 173 | const unsigned char **in, long len, const ASN1_ITEM *it, |
151 | * already present in the X509_NAME structure. | 174 | int tag, int aclass, char opt, ASN1_TLC *ctx) |
152 | */ | ||
153 | |||
154 | static void sk_internal_free(void *a) | ||
155 | { | ||
156 | sk_free(a); | ||
157 | } | ||
158 | |||
159 | static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it, | ||
160 | int tag, int aclass, char opt, ASN1_TLC *ctx) | ||
161 | { | 175 | { |
162 | const unsigned char *p = *in, *q; | 176 | const unsigned char *p = *in, *q; |
163 | union { STACK *s; ASN1_VALUE *a; } intname = {NULL}; | 177 | union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; |
178 | ASN1_VALUE *a; } intname = {NULL}; | ||
164 | union { X509_NAME *x; ASN1_VALUE *a; } nm = {NULL}; | 179 | union { X509_NAME *x; ASN1_VALUE *a; } nm = {NULL}; |
165 | int i, j, ret; | 180 | int i, j, ret; |
166 | STACK_OF(X509_NAME_ENTRY) *entries; | 181 | STACK_OF(X509_NAME_ENTRY) *entries; |
@@ -181,8 +196,8 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len | |||
181 | memcpy(nm.x->bytes->data, q, p - q); | 196 | memcpy(nm.x->bytes->data, q, p - q); |
182 | 197 | ||
183 | /* Convert internal representation to X509_NAME structure */ | 198 | /* Convert internal representation to X509_NAME structure */ |
184 | for(i = 0; i < sk_num(intname.s); i++) { | 199 | for(i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) { |
185 | entries = (STACK_OF(X509_NAME_ENTRY) *)sk_value(intname.s, i); | 200 | entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i); |
186 | for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { | 201 | for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { |
187 | entry = sk_X509_NAME_ENTRY_value(entries, j); | 202 | entry = sk_X509_NAME_ENTRY_value(entries, j); |
188 | entry->set = i; | 203 | entry->set = i; |
@@ -191,7 +206,10 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len | |||
191 | } | 206 | } |
192 | sk_X509_NAME_ENTRY_free(entries); | 207 | sk_X509_NAME_ENTRY_free(entries); |
193 | } | 208 | } |
194 | sk_free(intname.s); | 209 | sk_STACK_OF_X509_NAME_ENTRY_free(intname.s); |
210 | ret = x509_name_canon(nm.x); | ||
211 | if (!ret) | ||
212 | goto err; | ||
195 | nm.x->modified = 0; | 213 | nm.x->modified = 0; |
196 | *val = nm.a; | 214 | *val = nm.a; |
197 | *in = p; | 215 | *in = p; |
@@ -206,8 +224,12 @@ static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_IT | |||
206 | int ret; | 224 | int ret; |
207 | X509_NAME *a = (X509_NAME *)*val; | 225 | X509_NAME *a = (X509_NAME *)*val; |
208 | if(a->modified) { | 226 | if(a->modified) { |
209 | ret = x509_name_encode((X509_NAME *)a); | 227 | ret = x509_name_encode(a); |
210 | if(ret < 0) return ret; | 228 | if(ret < 0) |
229 | return ret; | ||
230 | ret = x509_name_canon(a); | ||
231 | if(ret < 0) | ||
232 | return ret; | ||
211 | } | 233 | } |
212 | ret = a->bytes->length; | 234 | ret = a->bytes->length; |
213 | if(out != NULL) { | 235 | if(out != NULL) { |
@@ -217,22 +239,35 @@ static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_IT | |||
217 | return ret; | 239 | return ret; |
218 | } | 240 | } |
219 | 241 | ||
242 | static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne) | ||
243 | { | ||
244 | sk_X509_NAME_ENTRY_free(ne); | ||
245 | } | ||
246 | |||
247 | static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) | ||
248 | { | ||
249 | sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); | ||
250 | } | ||
251 | |||
220 | static int x509_name_encode(X509_NAME *a) | 252 | static int x509_name_encode(X509_NAME *a) |
221 | { | 253 | { |
222 | union { STACK *s; ASN1_VALUE *a; } intname = {NULL}; | 254 | union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; |
255 | ASN1_VALUE *a; } intname = {NULL}; | ||
223 | int len; | 256 | int len; |
224 | unsigned char *p; | 257 | unsigned char *p; |
225 | STACK_OF(X509_NAME_ENTRY) *entries = NULL; | 258 | STACK_OF(X509_NAME_ENTRY) *entries = NULL; |
226 | X509_NAME_ENTRY *entry; | 259 | X509_NAME_ENTRY *entry; |
227 | int i, set = -1; | 260 | int i, set = -1; |
228 | intname.s = sk_new_null(); | 261 | intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null(); |
229 | if(!intname.s) goto memerr; | 262 | if(!intname.s) goto memerr; |
230 | for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { | 263 | for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { |
231 | entry = sk_X509_NAME_ENTRY_value(a->entries, i); | 264 | entry = sk_X509_NAME_ENTRY_value(a->entries, i); |
232 | if(entry->set != set) { | 265 | if(entry->set != set) { |
233 | entries = sk_X509_NAME_ENTRY_new_null(); | 266 | entries = sk_X509_NAME_ENTRY_new_null(); |
234 | if(!entries) goto memerr; | 267 | if(!entries) goto memerr; |
235 | if(!sk_push(intname.s, (char *)entries)) goto memerr; | 268 | if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, |
269 | entries)) | ||
270 | goto memerr; | ||
236 | set = entry->set; | 271 | set = entry->set; |
237 | } | 272 | } |
238 | if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr; | 273 | if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr; |
@@ -243,15 +278,222 @@ static int x509_name_encode(X509_NAME *a) | |||
243 | p=(unsigned char *)a->bytes->data; | 278 | p=(unsigned char *)a->bytes->data; |
244 | ASN1_item_ex_i2d(&intname.a, | 279 | ASN1_item_ex_i2d(&intname.a, |
245 | &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); | 280 | &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); |
246 | sk_pop_free(intname.s, sk_internal_free); | 281 | sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, |
282 | local_sk_X509_NAME_ENTRY_free); | ||
247 | a->modified = 0; | 283 | a->modified = 0; |
248 | return len; | 284 | return len; |
249 | memerr: | 285 | memerr: |
250 | sk_pop_free(intname.s, sk_internal_free); | 286 | sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, |
287 | local_sk_X509_NAME_ENTRY_free); | ||
251 | ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE); | 288 | ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE); |
252 | return -1; | 289 | return -1; |
253 | } | 290 | } |
254 | 291 | ||
292 | static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, | ||
293 | int indent, | ||
294 | const char *fname, | ||
295 | const ASN1_PCTX *pctx) | ||
296 | { | ||
297 | if (X509_NAME_print_ex(out, (X509_NAME *)*pval, | ||
298 | indent, pctx->nm_flags) <= 0) | ||
299 | return 0; | ||
300 | return 2; | ||
301 | } | ||
302 | |||
303 | /* This function generates the canonical encoding of the Name structure. | ||
304 | * In it all strings are converted to UTF8, leading, trailing and | ||
305 | * multiple spaces collapsed, converted to lower case and the leading | ||
306 | * SEQUENCE header removed. | ||
307 | * | ||
308 | * In future we could also normalize the UTF8 too. | ||
309 | * | ||
310 | * By doing this comparison of Name structures can be rapidly | ||
311 | * perfomed by just using memcmp() of the canonical encoding. | ||
312 | * By omitting the leading SEQUENCE name constraints of type | ||
313 | * dirName can also be checked with a simple memcmp(). | ||
314 | */ | ||
315 | |||
316 | static int x509_name_canon(X509_NAME *a) | ||
317 | { | ||
318 | unsigned char *p; | ||
319 | STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; | ||
320 | STACK_OF(X509_NAME_ENTRY) *entries = NULL; | ||
321 | X509_NAME_ENTRY *entry, *tmpentry = NULL; | ||
322 | int i, set = -1, ret = 0; | ||
323 | |||
324 | if (a->canon_enc) | ||
325 | { | ||
326 | OPENSSL_free(a->canon_enc); | ||
327 | a->canon_enc = NULL; | ||
328 | } | ||
329 | /* Special case: empty X509_NAME => null encoding */ | ||
330 | if (sk_X509_NAME_ENTRY_num(a->entries) == 0) | ||
331 | { | ||
332 | a->canon_enclen = 0; | ||
333 | return 1; | ||
334 | } | ||
335 | intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); | ||
336 | if(!intname) | ||
337 | goto err; | ||
338 | for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) | ||
339 | { | ||
340 | entry = sk_X509_NAME_ENTRY_value(a->entries, i); | ||
341 | if(entry->set != set) | ||
342 | { | ||
343 | entries = sk_X509_NAME_ENTRY_new_null(); | ||
344 | if(!entries) | ||
345 | goto err; | ||
346 | if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) | ||
347 | goto err; | ||
348 | set = entry->set; | ||
349 | } | ||
350 | tmpentry = X509_NAME_ENTRY_new(); | ||
351 | tmpentry->object = OBJ_dup(entry->object); | ||
352 | if (!asn1_string_canon(tmpentry->value, entry->value)) | ||
353 | goto err; | ||
354 | if(!sk_X509_NAME_ENTRY_push(entries, tmpentry)) | ||
355 | goto err; | ||
356 | tmpentry = NULL; | ||
357 | } | ||
358 | |||
359 | /* Finally generate encoding */ | ||
360 | |||
361 | a->canon_enclen = i2d_name_canon(intname, NULL); | ||
362 | |||
363 | p = OPENSSL_malloc(a->canon_enclen); | ||
364 | |||
365 | if (!p) | ||
366 | goto err; | ||
367 | |||
368 | a->canon_enc = p; | ||
369 | |||
370 | i2d_name_canon(intname, &p); | ||
371 | |||
372 | ret = 1; | ||
373 | |||
374 | err: | ||
375 | |||
376 | if (tmpentry) | ||
377 | X509_NAME_ENTRY_free(tmpentry); | ||
378 | if (intname) | ||
379 | sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, | ||
380 | local_sk_X509_NAME_ENTRY_pop_free); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | /* Bitmap of all the types of string that will be canonicalized. */ | ||
385 | |||
386 | #define ASN1_MASK_CANON \ | ||
387 | (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \ | ||
388 | | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \ | ||
389 | | B_ASN1_VISIBLESTRING) | ||
390 | |||
391 | |||
392 | static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) | ||
393 | { | ||
394 | unsigned char *to, *from; | ||
395 | int len, i; | ||
396 | |||
397 | /* If type not in bitmask just copy string across */ | ||
398 | if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) | ||
399 | { | ||
400 | out->type = in->type; | ||
401 | if (!ASN1_STRING_set(out, in->data, in->length)) | ||
402 | return 0; | ||
403 | return 1; | ||
404 | } | ||
405 | |||
406 | out->type = V_ASN1_UTF8STRING; | ||
407 | out->length = ASN1_STRING_to_UTF8(&out->data, in); | ||
408 | if (out->length == -1) | ||
409 | return 0; | ||
410 | |||
411 | to = out->data; | ||
412 | from = to; | ||
413 | |||
414 | len = out->length; | ||
415 | |||
416 | /* Convert string in place to canonical form. | ||
417 | * Ultimately we may need to handle a wider range of characters | ||
418 | * but for now ignore anything with MSB set and rely on the | ||
419 | * isspace() and tolower() functions. | ||
420 | */ | ||
421 | |||
422 | /* Ignore leading spaces */ | ||
423 | while((len > 0) && !(*from & 0x80) && isspace(*from)) | ||
424 | { | ||
425 | from++; | ||
426 | len--; | ||
427 | } | ||
428 | |||
429 | to = from + len - 1; | ||
430 | |||
431 | /* Ignore trailing spaces */ | ||
432 | while ((len > 0) && !(*to & 0x80) && isspace(*to)) | ||
433 | { | ||
434 | to--; | ||
435 | len--; | ||
436 | } | ||
437 | |||
438 | to = out->data; | ||
439 | |||
440 | i = 0; | ||
441 | while(i < len) | ||
442 | { | ||
443 | /* If MSB set just copy across */ | ||
444 | if (*from & 0x80) | ||
445 | { | ||
446 | *to++ = *from++; | ||
447 | i++; | ||
448 | } | ||
449 | /* Collapse multiple spaces */ | ||
450 | else if (isspace(*from)) | ||
451 | { | ||
452 | /* Copy one space across */ | ||
453 | *to++ = ' '; | ||
454 | /* Ignore subsequent spaces. Note: don't need to | ||
455 | * check len here because we know the last | ||
456 | * character is a non-space so we can't overflow. | ||
457 | */ | ||
458 | do | ||
459 | { | ||
460 | from++; | ||
461 | i++; | ||
462 | } | ||
463 | while(!(*from & 0x80) && isspace(*from)); | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | *to++ = tolower(*from++); | ||
468 | i++; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | out->length = to - out->data; | ||
473 | |||
474 | return 1; | ||
475 | |||
476 | } | ||
477 | |||
478 | static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname, | ||
479 | unsigned char **in) | ||
480 | { | ||
481 | int i, len, ltmp; | ||
482 | ASN1_VALUE *v; | ||
483 | STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname; | ||
484 | |||
485 | len = 0; | ||
486 | for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) | ||
487 | { | ||
488 | v = sk_ASN1_VALUE_value(intname, i); | ||
489 | ltmp = ASN1_item_ex_i2d(&v, in, | ||
490 | ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1); | ||
491 | if (ltmp < 0) | ||
492 | return ltmp; | ||
493 | len += ltmp; | ||
494 | } | ||
495 | return len; | ||
496 | } | ||
255 | 497 | ||
256 | int X509_NAME_set(X509_NAME **xn, X509_NAME *name) | 498 | int X509_NAME_set(X509_NAME **xn, X509_NAME *name) |
257 | { | 499 | { |