1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
40 extern int fprintf(FILE *strm
, const char *format
, .../* args */);
41 extern int fflush(FILE *stream
);
44 #define RIGHT_MARGIN 24
45 /*#define RAW_BYTES 1 */
47 static int prettyColumn
= 0;
50 getInteger256(unsigned char *data
, unsigned int nb
)
59 val
= (data
[0] << 8) | data
[1];
62 val
= (data
[0] << 16) | (data
[1] << 8) | data
[2];
65 val
= (data
[0] << 24) | (data
[1] << 16) | (data
[2] << 8) | data
[3];
68 PORT_SetError(SEC_ERROR_BAD_DER
);
76 prettyNewline(FILE *out
)
80 if (prettyColumn
!= -1) {
81 rv
= fprintf(out
, "\n");
84 PORT_SetError(SEC_ERROR_IO
);
92 prettyIndent(FILE *out
, unsigned level
)
97 if (prettyColumn
== -1) {
99 for (i
= 0; i
< level
; i
++) {
100 rv
= fprintf(out
, " ");
102 PORT_SetError(SEC_ERROR_IO
);
112 prettyPrintByte(FILE *out
, unsigned char item
, unsigned int level
)
116 rv
= prettyIndent(out
, level
);
120 rv
= fprintf(out
, "%02x ", item
);
122 PORT_SetError(SEC_ERROR_IO
);
127 if (prettyColumn
>= RIGHT_MARGIN
) {
128 return prettyNewline(out
);
135 prettyPrintLeaf(FILE *out
, unsigned char *data
,
136 unsigned int len
, unsigned int lv
)
141 for (i
= 0; i
< len
; i
++) {
142 rv
= prettyPrintByte(out
, *data
++, lv
);
146 return prettyNewline(out
);
150 prettyPrintStringStart(FILE *out
, unsigned char *str
,
151 unsigned int len
, unsigned int level
)
154 unsigned char buf
[BUF_SIZE
];
160 rv
= prettyNewline(out
);
164 rv
= prettyIndent(out
, level
);
168 memcpy(buf
, str
, len
);
171 rv
= fprintf(out
, "\"%s\"", buf
);
173 PORT_SetError(SEC_ERROR_IO
);
182 prettyPrintString(FILE *out
, unsigned char *str
,
183 unsigned int len
, unsigned int level
, PRBool raw
)
187 rv
= prettyPrintStringStart(out
, str
, len
, level
);
191 rv
= prettyNewline(out
);
196 rv
= prettyPrintLeaf(out
, str
, len
, level
);
205 prettyPrintTime(FILE *out
, unsigned char *str
,
206 unsigned int len
, unsigned int level
, PRBool raw
, PRBool utc
)
211 rv
= prettyPrintStringStart(out
, str
, len
, level
);
215 time_item
.data
= str
;
218 rv
= fprintf(out
, " (");
220 PORT_SetError(SEC_ERROR_IO
);
225 SECU_PrintUTCTime(out
, &time_item
, NULL
, 0);
227 SECU_PrintGeneralizedTime(out
, &time_item
, NULL
, 0);
229 rv
= fprintf(out
, ")");
231 PORT_SetError(SEC_ERROR_IO
);
235 rv
= prettyNewline(out
);
240 rv
= prettyPrintLeaf(out
, str
, len
, level
);
249 prettyPrintObjectID(FILE *out
, unsigned char *data
,
250 unsigned int len
, unsigned int level
, PRBool raw
)
260 * First print the Object Id in numeric format
263 rv
= prettyIndent(out
, level
);
270 rv
= fprintf(out
, "%lu %u ", val
, i
);
272 PORT_SetError(SEC_ERROR_IO
);
277 for (i
= 1; i
< len
; ++i
) {
281 val
= (val
<< 7) | (j
& 0x7f);
284 rv
= fprintf(out
, "%lu ", val
);
286 PORT_SetError(SEC_ERROR_IO
);
293 * Now try to look it up and print a symbolic version.
297 oiddata
= SECOID_FindOID(&oiditem
);
298 if (oiddata
!= NULL
) {
299 i
= PORT_Strlen(oiddata
->desc
);
300 if ((prettyColumn
+ 1 + (i
/ 3)) > RIGHT_MARGIN
) {
301 rv
= prettyNewline(out
);
306 rv
= prettyIndent(out
, level
);
310 rv
= fprintf(out
, "(%s)", oiddata
->desc
);
312 PORT_SetError(SEC_ERROR_IO
);
318 * Finally, on a new line, print the raw bytes (if requested).
321 rv
= prettyNewline(out
);
323 PORT_SetError(SEC_ERROR_IO
);
327 for (i
= 0; i
< len
; i
++) {
328 rv
= prettyPrintByte(out
, *data
++, level
);
334 return prettyNewline(out
);
337 static char *prettyTagType
[32] = {
373 prettyPrintTag(FILE *out
, unsigned char *src
, unsigned char *end
,
374 unsigned char *codep
, unsigned int level
, PRBool raw
)
377 unsigned char code
, tagnum
;
380 PORT_SetError(SEC_ERROR_BAD_DER
);
385 tagnum
= code
& SEC_ASN1_TAGNUM_MASK
;
388 * NOTE: This code does not (yet) handle the high-tag-number form!
390 if (tagnum
== SEC_ASN1_HIGH_TAG_NUMBER
) {
391 PORT_SetError(SEC_ERROR_BAD_DER
);
396 rv
= prettyPrintByte(out
, code
, level
);
398 rv
= prettyIndent(out
, level
);
403 if (code
& SEC_ASN1_CONSTRUCTED
) {
404 rv
= fprintf(out
, "C-");
406 PORT_SetError(SEC_ERROR_IO
);
411 switch (code
& SEC_ASN1_CLASS_MASK
) {
412 case SEC_ASN1_UNIVERSAL
:
413 rv
= fprintf(out
, "%s ", prettyTagType
[tagnum
]);
415 case SEC_ASN1_APPLICATION
:
416 rv
= fprintf(out
, "Application: %d ", tagnum
);
418 case SEC_ASN1_CONTEXT_SPECIFIC
:
419 rv
= fprintf(out
, "[%d] ", tagnum
);
421 case SEC_ASN1_PRIVATE
:
422 rv
= fprintf(out
, "Private: %d ", tagnum
);
427 PORT_SetError(SEC_ERROR_IO
);
437 prettyPrintLength(FILE *out
, unsigned char *data
, unsigned char *end
,
438 int *lenp
, PRBool
*indefinitep
, unsigned int lv
, PRBool raw
)
445 PORT_SetError(SEC_ERROR_BAD_DER
);
449 rv
= fprintf(out
, " ");
451 PORT_SetError(SEC_ERROR_IO
);
455 *indefinitep
= PR_FALSE
;
459 /* Multibyte length */
460 unsigned nb
= (unsigned) (lbyte
& 0x7f);
462 PORT_SetError(SEC_ERROR_BAD_DER
);
468 if ((data
+ nb
) > end
) {
469 PORT_SetError(SEC_ERROR_BAD_DER
);
472 il
= getInteger256(data
, nb
);
473 if (il
< 0) return -1;
474 *lenp
= (unsigned) il
;
477 *indefinitep
= PR_TRUE
;
483 rv
= prettyPrintByte(out
, lbyte
, lv
);
486 for (i
= 0; i
< nb
; i
++) {
487 rv
= prettyPrintByte(out
, data
[i
], lv
);
496 rv
= prettyPrintByte(out
, lbyte
, lv
);
502 rv
= fprintf(out
, "(indefinite)\n");
504 rv
= fprintf(out
, "(%d)\n", *lenp
);
506 PORT_SetError(SEC_ERROR_IO
);
515 prettyPrintItem(FILE *out
, unsigned char *data
, unsigned char *end
,
516 unsigned int lv
, PRBool raw
)
520 unsigned char *orig
= data
;
527 slen
= prettyPrintTag(out
, data
, end
, &code
, lv
, raw
);
532 lenLen
= prettyPrintLength(out
, data
, end
, &slen
, &indefinite
, lv
, raw
);
538 * Just quit now if slen more bytes puts us off the end.
540 if ((data
+ slen
) > end
) {
541 PORT_SetError(SEC_ERROR_BAD_DER
);
545 if (code
& SEC_ASN1_CONSTRUCTED
) {
546 if (slen
> 0 || indefinite
) {
547 slen
= prettyPrintItem(out
, data
,
548 slen
== 0 ? end
: data
+ slen
,
554 } else if (code
== 0) {
555 if (slen
!= 0 || lenLen
!= 1) {
556 PORT_SetError(SEC_ERROR_BAD_DER
);
562 case SEC_ASN1_PRINTABLE_STRING
:
563 case SEC_ASN1_IA5_STRING
:
564 case SEC_ASN1_VISIBLE_STRING
:
565 rv
= prettyPrintString(out
, data
, slen
, lv
+1, raw
);
569 case SEC_ASN1_UTC_TIME
:
570 rv
= prettyPrintTime(out
, data
, slen
, lv
+1, raw
, PR_TRUE
);
574 case SEC_ASN1_GENERALIZED_TIME
:
575 rv
= prettyPrintTime(out
, data
, slen
, lv
+1, raw
, PR_FALSE
);
579 case SEC_ASN1_OBJECT_ID
:
580 rv
= prettyPrintObjectID(out
, data
, slen
, lv
+1, raw
);
584 case SEC_ASN1_BOOLEAN
: /* could do nicer job */
585 case SEC_ASN1_INTEGER
: /* could do nicer job */
586 case SEC_ASN1_BIT_STRING
: /* could do nicer job */
587 case SEC_ASN1_OCTET_STRING
:
589 case SEC_ASN1_ENUMERATED
: /* could do nicer job, as INTEGER */
590 case SEC_ASN1_UTF8_STRING
:
591 case SEC_ASN1_T61_STRING
: /* print as printable string? */
592 case SEC_ASN1_UNIVERSAL_STRING
:
593 case SEC_ASN1_BMP_STRING
:
595 rv
= prettyPrintLeaf(out
, data
, slen
, lv
+1);
604 rv
= prettyNewline(out
);
612 DER_PrettyPrint(FILE *out
, SECItem
*it
, PRBool raw
)
618 rv
= prettyPrintItem(out
, it
->data
, it
->data
+ it
->len
, 0, raw
);