1 |
/* crypto/asn1/t_x509.c */ |
2 |
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 |
* All rights reserved. |
4 |
* |
5 |
* This package is an SSL implementation written |
6 |
* by Eric Young (eay@cryptsoft.com). |
7 |
* The implementation was written so as to conform with Netscapes SSL. |
8 |
* |
9 |
* This library is free for commercial and non-commercial use as long as |
10 |
* the following conditions are aheared to. The following conditions |
11 |
* apply to all code found in this distribution, be it the RC4, RSA, |
12 |
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 |
* included with this distribution is covered by the same copyright terms |
14 |
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 |
* |
16 |
* Copyright remains Eric Young's, and as such any Copyright notices in |
17 |
* the code are not to be removed. |
18 |
* If this package is used in a product, Eric Young should be given attribution |
19 |
* as the author of the parts of the library used. |
20 |
* This can be in the form of a textual message at program startup or |
21 |
* in documentation (online or textual) provided with the package. |
22 |
* |
23 |
* Redistribution and use in source and binary forms, with or without |
24 |
* modification, are permitted provided that the following conditions |
25 |
* are met: |
26 |
* 1. Redistributions of source code must retain the copyright |
27 |
* notice, this list of conditions and the following disclaimer. |
28 |
* 2. Redistributions in binary form must reproduce the above copyright |
29 |
* notice, this list of conditions and the following disclaimer in the |
30 |
* documentation and/or other materials provided with the distribution. |
31 |
* 3. All advertising materials mentioning features or use of this software |
32 |
* must display the following acknowledgement: |
33 |
* "This product includes cryptographic software written by |
34 |
* Eric Young (eay@cryptsoft.com)" |
35 |
* The word 'cryptographic' can be left out if the rouines from the library |
36 |
* being used are not cryptographic related :-). |
37 |
* 4. If you include any Windows specific code (or a derivative thereof) from |
38 |
* the apps directory (application code) you must include an acknowledgement: |
39 |
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 |
* |
41 |
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 |
* SUCH DAMAGE. |
52 |
* |
53 |
* The licence and distribution terms for any publically available version or |
54 |
* derivative of this code cannot be changed. i.e. this code cannot simply be |
55 |
* copied and put under another distribution licence |
56 |
* [including the GNU Public Licence.] |
57 |
*/ |
58 |
|
59 |
#include <stdio.h> |
60 |
#include "cryptlib.h" |
61 |
#include <openssl/buffer.h> |
62 |
#include <openssl/bn.h> |
63 |
#ifndef OPENSSL_NO_RSA |
64 |
# include <openssl/rsa.h> |
65 |
#endif |
66 |
#ifndef OPENSSL_NO_DSA |
67 |
# include <openssl/dsa.h> |
68 |
#endif |
69 |
#ifndef OPENSSL_NO_EC |
70 |
# include <openssl/ec.h> |
71 |
#endif |
72 |
#include <openssl/objects.h> |
73 |
#include <openssl/x509.h> |
74 |
#include <openssl/x509v3.h> |
75 |
#include "asn1_locl.h" |
76 |
|
77 |
#ifndef OPENSSL_NO_FP_API |
78 |
int X509_print_fp(FILE *fp, X509 *x) |
79 |
{ |
80 |
return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); |
81 |
} |
82 |
|
83 |
int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, |
84 |
unsigned long cflag) |
85 |
{ |
86 |
BIO *b; |
87 |
int ret; |
88 |
|
89 |
if ((b = BIO_new(BIO_s_file())) == NULL) { |
90 |
X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB); |
91 |
return (0); |
92 |
} |
93 |
BIO_set_fp(b, fp, BIO_NOCLOSE); |
94 |
ret = X509_print_ex(b, x, nmflag, cflag); |
95 |
BIO_free(b); |
96 |
return (ret); |
97 |
} |
98 |
#endif |
99 |
|
100 |
int X509_print(BIO *bp, X509 *x) |
101 |
{ |
102 |
return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT); |
103 |
} |
104 |
|
105 |
int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, |
106 |
unsigned long cflag) |
107 |
{ |
108 |
long l; |
109 |
int ret = 0, i; |
110 |
char *m = NULL, mlch = ' '; |
111 |
int nmindent = 0; |
112 |
X509_CINF *ci; |
113 |
ASN1_INTEGER *bs; |
114 |
EVP_PKEY *pkey = NULL; |
115 |
const char *neg; |
116 |
|
117 |
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { |
118 |
mlch = '\n'; |
119 |
nmindent = 12; |
120 |
} |
121 |
|
122 |
if (nmflags == X509_FLAG_COMPAT) |
123 |
nmindent = 16; |
124 |
|
125 |
ci = x->cert_info; |
126 |
if (!(cflag & X509_FLAG_NO_HEADER)) { |
127 |
if (BIO_write(bp, "Certificate:\n", 13) <= 0) |
128 |
goto err; |
129 |
if (BIO_write(bp, " Data:\n", 10) <= 0) |
130 |
goto err; |
131 |
} |
132 |
if (!(cflag & X509_FLAG_NO_VERSION)) { |
133 |
l = X509_get_version(x); |
134 |
if (BIO_printf(bp, "%8sVersion: %lu (0x%lx)\n", "", l + 1, l) <= 0) |
135 |
goto err; |
136 |
} |
137 |
if (!(cflag & X509_FLAG_NO_SERIAL)) { |
138 |
|
139 |
if (BIO_write(bp, " Serial Number:", 22) <= 0) |
140 |
goto err; |
141 |
|
142 |
bs = X509_get_serialNumber(x); |
143 |
if (bs->length < (int)sizeof(long) |
144 |
|| (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) { |
145 |
l = ASN1_INTEGER_get(bs); |
146 |
if (bs->type == V_ASN1_NEG_INTEGER) { |
147 |
l = -l; |
148 |
neg = "-"; |
149 |
} else |
150 |
neg = ""; |
151 |
if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, l, neg, l) <= 0) |
152 |
goto err; |
153 |
} else { |
154 |
neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; |
155 |
if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) |
156 |
goto err; |
157 |
|
158 |
for (i = 0; i < bs->length; i++) { |
159 |
if (BIO_printf(bp, "%02x%c", bs->data[i], |
160 |
((i + 1 == bs->length) ? '\n' : ':')) <= 0) |
161 |
goto err; |
162 |
} |
163 |
} |
164 |
|
165 |
} |
166 |
|
167 |
if (!(cflag & X509_FLAG_NO_SIGNAME)) { |
168 |
if (X509_signature_print(bp, ci->signature, NULL) <= 0) |
169 |
goto err; |
170 |
#if 0 |
171 |
if (BIO_printf(bp, "%8sSignature Algorithm: ", "") <= 0) |
172 |
goto err; |
173 |
if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0) |
174 |
goto err; |
175 |
if (BIO_puts(bp, "\n") <= 0) |
176 |
goto err; |
177 |
#endif |
178 |
} |
179 |
|
180 |
if (!(cflag & X509_FLAG_NO_ISSUER)) { |
181 |
if (BIO_printf(bp, " Issuer:%c", mlch) <= 0) |
182 |
goto err; |
183 |
if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags) |
184 |
< 0) |
185 |
goto err; |
186 |
if (BIO_write(bp, "\n", 1) <= 0) |
187 |
goto err; |
188 |
} |
189 |
if (!(cflag & X509_FLAG_NO_VALIDITY)) { |
190 |
if (BIO_write(bp, " Validity\n", 17) <= 0) |
191 |
goto err; |
192 |
if (BIO_write(bp, " Not Before: ", 24) <= 0) |
193 |
goto err; |
194 |
if (!ASN1_TIME_print(bp, X509_get_notBefore(x))) |
195 |
goto err; |
196 |
if (BIO_write(bp, "\n Not After : ", 25) <= 0) |
197 |
goto err; |
198 |
if (!ASN1_TIME_print(bp, X509_get_notAfter(x))) |
199 |
goto err; |
200 |
if (BIO_write(bp, "\n", 1) <= 0) |
201 |
goto err; |
202 |
} |
203 |
if (!(cflag & X509_FLAG_NO_SUBJECT)) { |
204 |
if (BIO_printf(bp, " Subject:%c", mlch) <= 0) |
205 |
goto err; |
206 |
if (X509_NAME_print_ex |
207 |
(bp, X509_get_subject_name(x), nmindent, nmflags) < 0) |
208 |
goto err; |
209 |
if (BIO_write(bp, "\n", 1) <= 0) |
210 |
goto err; |
211 |
} |
212 |
if (!(cflag & X509_FLAG_NO_PUBKEY)) { |
213 |
if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) |
214 |
goto err; |
215 |
if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) |
216 |
goto err; |
217 |
if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) |
218 |
goto err; |
219 |
if (BIO_puts(bp, "\n") <= 0) |
220 |
goto err; |
221 |
|
222 |
pkey = X509_get_pubkey(x); |
223 |
if (pkey == NULL) { |
224 |
BIO_printf(bp, "%12sUnable to load Public Key\n", ""); |
225 |
ERR_print_errors(bp); |
226 |
} else { |
227 |
EVP_PKEY_print_public(bp, pkey, 16, NULL); |
228 |
EVP_PKEY_free(pkey); |
229 |
} |
230 |
} |
231 |
|
232 |
if (!(cflag & X509_FLAG_NO_EXTENSIONS)) |
233 |
X509V3_extensions_print(bp, "X509v3 extensions", |
234 |
ci->extensions, cflag, 8); |
235 |
|
236 |
if (!(cflag & X509_FLAG_NO_SIGDUMP)) { |
237 |
if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0) |
238 |
goto err; |
239 |
} |
240 |
if (!(cflag & X509_FLAG_NO_AUX)) { |
241 |
if (!X509_CERT_AUX_print(bp, x->aux, 0)) |
242 |
goto err; |
243 |
} |
244 |
ret = 1; |
245 |
err: |
246 |
if (m != NULL) |
247 |
OPENSSL_free(m); |
248 |
return (ret); |
249 |
} |
250 |
|
251 |
int X509_ocspid_print(BIO *bp, X509 *x) |
252 |
{ |
253 |
unsigned char *der = NULL; |
254 |
unsigned char *dertmp; |
255 |
int derlen; |
256 |
int i; |
257 |
unsigned char SHA1md[SHA_DIGEST_LENGTH]; |
258 |
|
259 |
/* |
260 |
* display the hash of the subject as it would appear in OCSP requests |
261 |
*/ |
262 |
if (BIO_printf(bp, " Subject OCSP hash: ") <= 0) |
263 |
goto err; |
264 |
derlen = i2d_X509_NAME(x->cert_info->subject, NULL); |
265 |
if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL) |
266 |
goto err; |
267 |
i2d_X509_NAME(x->cert_info->subject, &dertmp); |
268 |
|
269 |
if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL)) |
270 |
goto err; |
271 |
for (i = 0; i < SHA_DIGEST_LENGTH; i++) { |
272 |
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) |
273 |
goto err; |
274 |
} |
275 |
OPENSSL_free(der); |
276 |
der = NULL; |
277 |
|
278 |
/* |
279 |
* display the hash of the public key as it would appear in OCSP requests |
280 |
*/ |
281 |
if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0) |
282 |
goto err; |
283 |
|
284 |
if (!EVP_Digest(x->cert_info->key->public_key->data, |
285 |
x->cert_info->key->public_key->length, |
286 |
SHA1md, NULL, EVP_sha1(), NULL)) |
287 |
goto err; |
288 |
for (i = 0; i < SHA_DIGEST_LENGTH; i++) { |
289 |
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0) |
290 |
goto err; |
291 |
} |
292 |
BIO_printf(bp, "\n"); |
293 |
|
294 |
return (1); |
295 |
err: |
296 |
if (der != NULL) |
297 |
OPENSSL_free(der); |
298 |
return (0); |
299 |
} |
300 |
|
301 |
int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) |
302 |
{ |
303 |
const unsigned char *s; |
304 |
int i, n; |
305 |
|
306 |
n = sig->length; |
307 |
s = sig->data; |
308 |
for (i = 0; i < n; i++) { |
309 |
if ((i % 18) == 0) { |
310 |
if (BIO_write(bp, "\n", 1) <= 0) |
311 |
return 0; |
312 |
if (BIO_indent(bp, indent, indent) <= 0) |
313 |
return 0; |
314 |
} |
315 |
if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0) |
316 |
return 0; |
317 |
} |
318 |
if (BIO_write(bp, "\n", 1) != 1) |
319 |
return 0; |
320 |
|
321 |
return 1; |
322 |
} |
323 |
|
324 |
int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig) |
325 |
{ |
326 |
int sig_nid; |
327 |
if (BIO_puts(bp, " Signature Algorithm: ") <= 0) |
328 |
return 0; |
329 |
if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) |
330 |
return 0; |
331 |
|
332 |
sig_nid = OBJ_obj2nid(sigalg->algorithm); |
333 |
if (sig_nid != NID_undef) { |
334 |
int pkey_nid, dig_nid; |
335 |
const EVP_PKEY_ASN1_METHOD *ameth; |
336 |
if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) { |
337 |
ameth = EVP_PKEY_asn1_find(NULL, pkey_nid); |
338 |
if (ameth && ameth->sig_print) |
339 |
return ameth->sig_print(bp, sigalg, sig, 9, 0); |
340 |
} |
341 |
} |
342 |
if (sig) |
343 |
return X509_signature_dump(bp, sig, 9); |
344 |
else if (BIO_puts(bp, "\n") <= 0) |
345 |
return 0; |
346 |
return 1; |
347 |
} |
348 |
|
349 |
int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) |
350 |
{ |
351 |
int i, n; |
352 |
char buf[80]; |
353 |
const char *p; |
354 |
|
355 |
if (v == NULL) |
356 |
return (0); |
357 |
n = 0; |
358 |
p = (const char *)v->data; |
359 |
for (i = 0; i < v->length; i++) { |
360 |
if ((p[i] > '~') || ((p[i] < ' ') && |
361 |
(p[i] != '\n') && (p[i] != '\r'))) |
362 |
buf[n] = '.'; |
363 |
else |
364 |
buf[n] = p[i]; |
365 |
n++; |
366 |
if (n >= 80) { |
367 |
if (BIO_write(bp, buf, n) <= 0) |
368 |
return (0); |
369 |
n = 0; |
370 |
} |
371 |
} |
372 |
if (n > 0) |
373 |
if (BIO_write(bp, buf, n) <= 0) |
374 |
return (0); |
375 |
return (1); |
376 |
} |
377 |
|
378 |
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) |
379 |
{ |
380 |
if (tm->type == V_ASN1_UTCTIME) |
381 |
return ASN1_UTCTIME_print(bp, tm); |
382 |
if (tm->type == V_ASN1_GENERALIZEDTIME) |
383 |
return ASN1_GENERALIZEDTIME_print(bp, tm); |
384 |
BIO_write(bp, "Bad time value", 14); |
385 |
return (0); |
386 |
} |
387 |
|
388 |
static const char *mon[12] = { |
389 |
"Jan", "Feb", "Mar", "Apr", "May", "Jun", |
390 |
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
391 |
}; |
392 |
|
393 |
int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) |
394 |
{ |
395 |
char *v; |
396 |
int gmt = 0; |
397 |
int i; |
398 |
int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0; |
399 |
char *f = NULL; |
400 |
int f_len = 0; |
401 |
|
402 |
i = tm->length; |
403 |
v = (char *)tm->data; |
404 |
|
405 |
if (i < 12) |
406 |
goto err; |
407 |
if (v[i - 1] == 'Z') |
408 |
gmt = 1; |
409 |
for (i = 0; i < 12; i++) |
410 |
if ((v[i] > '9') || (v[i] < '0')) |
411 |
goto err; |
412 |
y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 |
413 |
+ (v[2] - '0') * 10 + (v[3] - '0'); |
414 |
M = (v[4] - '0') * 10 + (v[5] - '0'); |
415 |
if ((M > 12) || (M < 1)) |
416 |
goto err; |
417 |
d = (v[6] - '0') * 10 + (v[7] - '0'); |
418 |
h = (v[8] - '0') * 10 + (v[9] - '0'); |
419 |
m = (v[10] - '0') * 10 + (v[11] - '0'); |
420 |
if (tm->length >= 14 && |
421 |
(v[12] >= '0') && (v[12] <= '9') && |
422 |
(v[13] >= '0') && (v[13] <= '9')) { |
423 |
s = (v[12] - '0') * 10 + (v[13] - '0'); |
424 |
/* Check for fractions of seconds. */ |
425 |
if (tm->length >= 15 && v[14] == '.') { |
426 |
int l = tm->length; |
427 |
f = &v[14]; /* The decimal point. */ |
428 |
f_len = 1; |
429 |
while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9') |
430 |
++f_len; |
431 |
} |
432 |
} |
433 |
|
434 |
if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s", |
435 |
mon[M - 1], d, h, m, s, f_len, f, y, |
436 |
(gmt) ? " GMT" : "") <= 0) |
437 |
return (0); |
438 |
else |
439 |
return (1); |
440 |
err: |
441 |
BIO_write(bp, "Bad time value", 14); |
442 |
return (0); |
443 |
} |
444 |
|
445 |
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) |
446 |
{ |
447 |
const char *v; |
448 |
int gmt = 0; |
449 |
int i; |
450 |
int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0; |
451 |
|
452 |
i = tm->length; |
453 |
v = (const char *)tm->data; |
454 |
|
455 |
if (i < 10) |
456 |
goto err; |
457 |
if (v[i - 1] == 'Z') |
458 |
gmt = 1; |
459 |
for (i = 0; i < 10; i++) |
460 |
if ((v[i] > '9') || (v[i] < '0')) |
461 |
goto err; |
462 |
y = (v[0] - '0') * 10 + (v[1] - '0'); |
463 |
if (y < 50) |
464 |
y += 100; |
465 |
M = (v[2] - '0') * 10 + (v[3] - '0'); |
466 |
if ((M > 12) || (M < 1)) |
467 |
goto err; |
468 |
d = (v[4] - '0') * 10 + (v[5] - '0'); |
469 |
h = (v[6] - '0') * 10 + (v[7] - '0'); |
470 |
m = (v[8] - '0') * 10 + (v[9] - '0'); |
471 |
if (tm->length >= 12 && |
472 |
(v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9')) |
473 |
s = (v[10] - '0') * 10 + (v[11] - '0'); |
474 |
|
475 |
if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", |
476 |
mon[M - 1], d, h, m, s, y + 1900, |
477 |
(gmt) ? " GMT" : "") <= 0) |
478 |
return (0); |
479 |
else |
480 |
return (1); |
481 |
err: |
482 |
BIO_write(bp, "Bad time value", 14); |
483 |
return (0); |
484 |
} |
485 |
|
486 |
int X509_NAME_print(BIO *bp, X509_NAME *name, int obase) |
487 |
{ |
488 |
char *s, *c, *b; |
489 |
int ret = 0, l, i; |
490 |
|
491 |
l = 80 - 2 - obase; |
492 |
|
493 |
b = X509_NAME_oneline(name, NULL, 0); |
494 |
if (!b) |
495 |
return 0; |
496 |
if (!*b) { |
497 |
OPENSSL_free(b); |
498 |
return 1; |
499 |
} |
500 |
s = b + 1; /* skip the first slash */ |
501 |
|
502 |
c = s; |
503 |
for (;;) { |
504 |
#ifndef CHARSET_EBCDIC |
505 |
if (((*s == '/') && |
506 |
((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') || |
507 |
((s[2] >= 'A') |
508 |
&& (s[2] <= 'Z') |
509 |
&& (s[3] == '=')) |
510 |
))) || (*s == '\0')) |
511 |
#else |
512 |
if (((*s == '/') && |
513 |
(isupper(s[1]) && ((s[2] == '=') || |
514 |
(isupper(s[2]) && (s[3] == '=')) |
515 |
))) || (*s == '\0')) |
516 |
#endif |
517 |
{ |
518 |
i = s - c; |
519 |
if (BIO_write(bp, c, i) != i) |
520 |
goto err; |
521 |
c = s + 1; /* skip following slash */ |
522 |
if (*s != '\0') { |
523 |
if (BIO_write(bp, ", ", 2) != 2) |
524 |
goto err; |
525 |
} |
526 |
l--; |
527 |
} |
528 |
if (*s == '\0') |
529 |
break; |
530 |
s++; |
531 |
l--; |
532 |
} |
533 |
|
534 |
ret = 1; |
535 |
if (0) { |
536 |
err: |
537 |
X509err(X509_F_X509_NAME_PRINT, ERR_R_BUF_LIB); |
538 |
} |
539 |
OPENSSL_free(b); |
540 |
return (ret); |
541 |
} |