1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
60 #include "internal/cryptlib.h"
61 #include <openssl/asn1t.h>
62 #include <openssl/x509.h>
63 #include "internal/x509_int.h"
64 #include "internal/asn1_int.h"
67 static int x509_name_ex_d2i(ASN1_VALUE
**val
,
68 const unsigned char **in
, long len
,
70 int tag
, int aclass
, char opt
, ASN1_TLC
*ctx
);
72 static int x509_name_ex_i2d(ASN1_VALUE
**val
, unsigned char **out
,
73 const ASN1_ITEM
*it
, int tag
, int aclass
);
74 static int x509_name_ex_new(ASN1_VALUE
**val
, const ASN1_ITEM
*it
);
75 static void x509_name_ex_free(ASN1_VALUE
**val
, const ASN1_ITEM
*it
);
77 static int x509_name_encode(X509_NAME
*a
);
78 static int x509_name_canon(X509_NAME
*a
);
79 static int asn1_string_canon(ASN1_STRING
*out
, ASN1_STRING
*in
);
80 static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY
) * intname
,
83 static int x509_name_ex_print(BIO
*out
, ASN1_VALUE
**pval
,
85 const char *fname
, const ASN1_PCTX
*pctx
);
87 ASN1_SEQUENCE(X509_NAME_ENTRY
) = {
88 ASN1_SIMPLE(X509_NAME_ENTRY
, object
, ASN1_OBJECT
),
89 ASN1_SIMPLE(X509_NAME_ENTRY
, value
, ASN1_PRINTABLE
)
90 } ASN1_SEQUENCE_END(X509_NAME_ENTRY
)
92 IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY
)
93 IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY
)
96 * For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so
97 * declare two template wrappers for this
100 ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES
) =
101 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF
, 0, RDNS
, X509_NAME_ENTRY
)
102 static_ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES
)
104 ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL
) =
105 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF
, 0, Name
, X509_NAME_ENTRIES
)
106 static_ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL
)
109 * Normally that's where it would end: we'd have two nested STACK structures
110 * representing the ASN1. Unfortunately X509_NAME uses a completely different
111 * form and caches encodings so we have to process the internal form and
112 * convert to the external form.
115 static const ASN1_EXTERN_FUNCS x509_name_ff
= {
119 0, /* Default clear behaviour is OK */
125 IMPLEMENT_EXTERN_ASN1(X509_NAME
, V_ASN1_SEQUENCE
, x509_name_ff
)
127 IMPLEMENT_ASN1_FUNCTIONS(X509_NAME
)
129 IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME
)
131 static int x509_name_ex_new(ASN1_VALUE
**val
, const ASN1_ITEM
*it
)
133 X509_NAME
*ret
= OPENSSL_zalloc(sizeof(*ret
));
137 if ((ret
->entries
= sk_X509_NAME_ENTRY_new_null()) == NULL
)
139 if ((ret
->bytes
= BUF_MEM_new()) == NULL
)
142 *val
= (ASN1_VALUE
*)ret
;
146 ASN1err(ASN1_F_X509_NAME_EX_NEW
, ERR_R_MALLOC_FAILURE
);
148 sk_X509_NAME_ENTRY_free(ret
->entries
);
154 static void x509_name_ex_free(ASN1_VALUE
**pval
, const ASN1_ITEM
*it
)
160 a
= (X509_NAME
*)*pval
;
162 BUF_MEM_free(a
->bytes
);
163 sk_X509_NAME_ENTRY_pop_free(a
->entries
, X509_NAME_ENTRY_free
);
164 OPENSSL_free(a
->canon_enc
);
169 static int x509_name_ex_d2i(ASN1_VALUE
**val
,
170 const unsigned char **in
, long len
,
171 const ASN1_ITEM
*it
, int tag
, int aclass
,
172 char opt
, ASN1_TLC
*ctx
)
174 const unsigned char *p
= *in
, *q
;
176 STACK_OF(STACK_OF_X509_NAME_ENTRY
) *s
;
188 STACK_OF(X509_NAME_ENTRY
) *entries
;
189 X509_NAME_ENTRY
*entry
;
192 /* Get internal representation of Name */
193 ret
= ASN1_item_ex_d2i(&intname
.a
,
194 &p
, len
, ASN1_ITEM_rptr(X509_NAME_INTERNAL
),
195 tag
, aclass
, opt
, ctx
);
201 x509_name_ex_free(val
, NULL
);
202 if (!x509_name_ex_new(&nm
.a
, NULL
))
204 /* We've decoded it: now cache encoding */
205 if (!BUF_MEM_grow(nm
.x
->bytes
, p
- q
))
207 memcpy(nm
.x
->bytes
->data
, q
, p
- q
);
209 /* Convert internal representation to X509_NAME structure */
210 for (i
= 0; i
< sk_STACK_OF_X509_NAME_ENTRY_num(intname
.s
); i
++) {
211 entries
= sk_STACK_OF_X509_NAME_ENTRY_value(intname
.s
, i
);
212 for (j
= 0; j
< sk_X509_NAME_ENTRY_num(entries
); j
++) {
213 entry
= sk_X509_NAME_ENTRY_value(entries
, j
);
215 if (!sk_X509_NAME_ENTRY_push(nm
.x
->entries
, entry
))
218 sk_X509_NAME_ENTRY_free(entries
);
220 sk_STACK_OF_X509_NAME_ENTRY_free(intname
.s
);
221 ret
= x509_name_canon(nm
.x
);
229 X509_NAME_free(nm
.x
);
230 ASN1err(ASN1_F_X509_NAME_EX_D2I
, ERR_R_NESTED_ASN1_ERROR
);
234 static int x509_name_ex_i2d(ASN1_VALUE
**val
, unsigned char **out
,
235 const ASN1_ITEM
*it
, int tag
, int aclass
)
238 X509_NAME
*a
= (X509_NAME
*)*val
;
240 ret
= x509_name_encode(a
);
243 ret
= x509_name_canon(a
);
247 ret
= a
->bytes
->length
;
249 memcpy(*out
, a
->bytes
->data
, ret
);
255 static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY
) *ne
)
257 sk_X509_NAME_ENTRY_free(ne
);
260 static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY
) *ne
)
262 sk_X509_NAME_ENTRY_pop_free(ne
, X509_NAME_ENTRY_free
);
265 static int x509_name_encode(X509_NAME
*a
)
268 STACK_OF(STACK_OF_X509_NAME_ENTRY
) *s
;
275 STACK_OF(X509_NAME_ENTRY
) *entries
= NULL
;
276 X509_NAME_ENTRY
*entry
;
278 intname
.s
= sk_STACK_OF_X509_NAME_ENTRY_new_null();
281 for (i
= 0; i
< sk_X509_NAME_ENTRY_num(a
->entries
); i
++) {
282 entry
= sk_X509_NAME_ENTRY_value(a
->entries
, i
);
283 if (entry
->set
!= set
) {
284 entries
= sk_X509_NAME_ENTRY_new_null();
287 if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname
.s
, entries
))
291 if (!sk_X509_NAME_ENTRY_push(entries
, entry
))
294 len
= ASN1_item_ex_i2d(&intname
.a
, NULL
,
295 ASN1_ITEM_rptr(X509_NAME_INTERNAL
), -1, -1);
296 if (!BUF_MEM_grow(a
->bytes
, len
))
298 p
= (unsigned char *)a
->bytes
->data
;
299 ASN1_item_ex_i2d(&intname
.a
,
300 &p
, ASN1_ITEM_rptr(X509_NAME_INTERNAL
), -1, -1);
301 sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname
.s
,
302 local_sk_X509_NAME_ENTRY_free
);
306 sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname
.s
,
307 local_sk_X509_NAME_ENTRY_free
);
308 ASN1err(ASN1_F_X509_NAME_ENCODE
, ERR_R_MALLOC_FAILURE
);
312 static int x509_name_ex_print(BIO
*out
, ASN1_VALUE
**pval
,
314 const char *fname
, const ASN1_PCTX
*pctx
)
316 if (X509_NAME_print_ex(out
, (X509_NAME
*)*pval
,
317 indent
, pctx
->nm_flags
) <= 0)
323 * This function generates the canonical encoding of the Name structure. In
324 * it all strings are converted to UTF8, leading, trailing and multiple
325 * spaces collapsed, converted to lower case and the leading SEQUENCE header
326 * removed. In future we could also normalize the UTF8 too. By doing this
327 * comparison of Name structures can be rapidly perfomed by just using
328 * memcmp() of the canonical encoding. By omitting the leading SEQUENCE name
329 * constraints of type dirName can also be checked with a simple memcmp().
332 static int x509_name_canon(X509_NAME
*a
)
335 STACK_OF(STACK_OF_X509_NAME_ENTRY
) *intname
= NULL
;
336 STACK_OF(X509_NAME_ENTRY
) *entries
= NULL
;
337 X509_NAME_ENTRY
*entry
, *tmpentry
= NULL
;
338 int i
, set
= -1, ret
= 0;
340 OPENSSL_free(a
->canon_enc
);
342 /* Special case: empty X509_NAME => null encoding */
343 if (sk_X509_NAME_ENTRY_num(a
->entries
) == 0) {
347 intname
= sk_STACK_OF_X509_NAME_ENTRY_new_null();
350 for (i
= 0; i
< sk_X509_NAME_ENTRY_num(a
->entries
); i
++) {
351 entry
= sk_X509_NAME_ENTRY_value(a
->entries
, i
);
352 if (entry
->set
!= set
) {
353 entries
= sk_X509_NAME_ENTRY_new_null();
356 if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname
, entries
))
360 tmpentry
= X509_NAME_ENTRY_new();
361 if (tmpentry
== NULL
)
363 tmpentry
->object
= OBJ_dup(entry
->object
);
364 if (!asn1_string_canon(tmpentry
->value
, entry
->value
))
366 if (!sk_X509_NAME_ENTRY_push(entries
, tmpentry
))
371 /* Finally generate encoding */
373 a
->canon_enclen
= i2d_name_canon(intname
, NULL
);
375 p
= OPENSSL_malloc(a
->canon_enclen
);
382 i2d_name_canon(intname
, &p
);
388 X509_NAME_ENTRY_free(tmpentry
);
389 sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname
,
390 local_sk_X509_NAME_ENTRY_pop_free
);
394 /* Bitmap of all the types of string that will be canonicalized. */
396 #define ASN1_MASK_CANON \
397 (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
398 | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
399 | B_ASN1_VISIBLESTRING)
401 static int asn1_string_canon(ASN1_STRING
*out
, ASN1_STRING
*in
)
403 unsigned char *to
, *from
;
406 /* If type not in bitmask just copy string across */
407 if (!(ASN1_tag2bit(in
->type
) & ASN1_MASK_CANON
)) {
408 if (!ASN1_STRING_copy(out
, in
))
413 out
->type
= V_ASN1_UTF8STRING
;
414 out
->length
= ASN1_STRING_to_UTF8(&out
->data
, in
);
415 if (out
->length
== -1)
424 * Convert string in place to canonical form. Ultimately we may need to
425 * handle a wider range of characters but for now ignore anything with
426 * MSB set and rely on the isspace() and tolower() functions.
429 /* Ignore leading spaces */
430 while ((len
> 0) && !(*from
& 0x80) && isspace(*from
)) {
437 /* Ignore trailing spaces */
438 while ((len
> 0) && !(*to
& 0x80) && isspace(*to
)) {
447 /* If MSB set just copy across */
452 /* Collapse multiple spaces */
453 else if (isspace(*from
)) {
454 /* Copy one space across */
457 * Ignore subsequent spaces. Note: don't need to check len here
458 * because we know the last character is a non-space so we can't
465 while (!(*from
& 0x80) && isspace(*from
));
467 *to
++ = tolower(*from
);
473 out
->length
= to
- out
->data
;
479 static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY
) * _intname
,
484 STACK_OF(ASN1_VALUE
) *intname
= (STACK_OF(ASN1_VALUE
) *)_intname
;
487 for (i
= 0; i
< sk_ASN1_VALUE_num(intname
); i
++) {
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);
498 int X509_NAME_set(X509_NAME
**xn
, X509_NAME
*name
)
506 in
= X509_NAME_dup(name
);
512 return (*xn
!= NULL
);
515 int X509_NAME_print(BIO
*bp
, X509_NAME
*name
, int obase
)
522 b
= X509_NAME_oneline(name
, NULL
, 0);
529 s
= b
+ 1; /* skip the first slash */
533 #ifndef CHARSET_EBCDIC
535 ((s
[1] >= 'A') && (s
[1] <= 'Z') && ((s
[2] == '=') ||
542 (isupper(s
[1]) && ((s
[2] == '=') ||
543 (isupper(s
[2]) && (s
[3] == '='))
548 if (BIO_write(bp
, c
, i
) != i
)
550 c
= s
+ 1; /* skip following slash */
552 if (BIO_write(bp
, ", ", 2) != 2)
566 X509err(X509_F_X509_NAME_PRINT
, ERR_R_BUF_LIB
);