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 ***** */
38 static const char CVS_ID
[] = "@(#) $RCSfile: asn1.c,v $ $Revision: 1.4 $ $Date: 2005/01/20 02:25:44 $";
44 * At this point in time, this file contains the NSS wrappers for
45 * the old "SEC" ASN.1 encoder/decoder stuff.
56 * The pointer-tracking stuff
60 extern const NSSError NSS_ERROR_INTERNAL_ERROR
;
62 static nssPointerTracker decoder_pointer_tracker
;
67 const nssASN1Decoder
*decoder
72 rv
= nssPointerTracker_initialize(&decoder_pointer_tracker
);
73 if( PR_SUCCESS
!= rv
) {
77 rv
= nssPointerTracker_add(&decoder_pointer_tracker
, decoder
);
78 if( PR_SUCCESS
!= rv
) {
79 NSSError e
= NSS_GetError();
80 if( NSS_ERROR_NO_MEMORY
!= e
) {
81 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
91 decoder_remove_pointer
93 const nssASN1Decoder
*decoder
98 rv
= nssPointerTracker_remove(&decoder_pointer_tracker
, decoder
);
99 if( PR_SUCCESS
!= rv
) {
100 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
107 * nssASN1Decoder_verify
109 * This routine is only available in debug builds.
111 * If the specified pointer is a valid pointer to an nssASN1Decoder
112 * object, this routine will return PR_SUCCESS. Otherwise, it will
113 * put an error on the error stack and return PR_FAILURE.
115 * The error may be one of the following values:
116 * NSS_ERROR_INVALID_ASN1DECODER
119 * PR_FAILURE upon error
120 * PR_SUCCESS upon success
123 NSS_IMPLEMENT PRStatus
124 nssASN1Decoder_verify
126 nssASN1Decoder
*decoder
131 rv
= nssPointerTracker_initialize(&decoder_pointer_tracker
);
132 if( PR_SUCCESS
!= rv
) {
136 rv
= nssPointerTracker_verify(&decoder_pointer_tracker
, decoder
);
137 if( PR_SUCCESS
!= rv
) {
138 nss_SetError(NSS_ERROR_INVALID_ASN1DECODER
);
145 static nssPointerTracker encoder_pointer_tracker
;
150 const nssASN1Encoder
*encoder
155 rv
= nssPointerTracker_initialize(&encoder_pointer_tracker
);
156 if( PR_SUCCESS
!= rv
) {
160 rv
= nssPointerTracker_add(&encoder_pointer_tracker
, encoder
);
161 if( PR_SUCCESS
!= rv
) {
162 NSSError e
= NSS_GetError();
163 if( NSS_ERROR_NO_MEMORY
!= e
) {
164 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
174 encoder_remove_pointer
176 const nssASN1Encoder
*encoder
181 rv
= nssPointerTracker_remove(&encoder_pointer_tracker
, encoder
);
182 if( PR_SUCCESS
!= rv
) {
183 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
190 * nssASN1Encoder_verify
192 * This routine is only available in debug builds.
194 * If the specified pointer is a valid pointer to an nssASN1Encoder
195 * object, this routine will return PR_SUCCESS. Otherwise, it will
196 * put an error on the error stack and return PR_FAILURE.
198 * The error may be one of the following values:
199 * NSS_ERROR_INVALID_ASN1ENCODER
202 * PR_FAILURE upon error
203 * PR_SUCCESS upon success
206 NSS_IMPLEMENT PRStatus
207 nssASN1Encoder_verify
209 nssASN1Encoder
*encoder
214 rv
= nssPointerTracker_initialize(&encoder_pointer_tracker
);
215 if( PR_SUCCESS
!= rv
) {
219 rv
= nssPointerTracker_verify(&encoder_pointer_tracker
, encoder
);
220 if( PR_SUCCESS
!= rv
) {
221 nss_SetError(NSS_ERROR_INVALID_ASN1ENCODER
);
230 * nssASN1Decoder_Create
232 * This routine creates an ASN.1 Decoder, which will use the specified
233 * template to decode a datastream into the specified destination
234 * structure. If the optional arena argument is non-NULL, blah blah
235 * blah. XXX fgmr Should we include an nssASN1EncodingType argument,
236 * as a hint? Or is each encoding distinctive? This routine may
237 * return NULL upon error, in which case an error will have been
238 * placed upon the error stack.
240 * The error may be one of the following values:
241 * NSS_ERROR_NO_MEMORY
242 * NSS_ERROR_INVALID_ARENA
243 * NSS_ERROR_INVALID_POINTER
248 * A pointer to an ASN.1 Decoder upon success.
251 NSS_IMPLEMENT nssASN1Decoder
*
252 nssASN1Decoder_Create
256 const nssASN1Template
template[]
259 SEC_ASN1DecoderContext
*rv
;
260 PLArenaPool
*hack
= (PLArenaPool
*)arenaOpt
;
263 if( (NSSArena
*)NULL
!= arenaOpt
) {
264 if( PR_SUCCESS
!= nssArena_verifyPointer(arenaOpt
) ) {
265 return (nssASN1Decoder
*)NULL
;
270 * May destination be NULL? I'd think so, since one might
271 * have only a filter proc. But if not, check the pointer here.
274 if( (nssASN1Template
*)NULL
== template ) {
275 nss_SetError(NSS_ERROR_INVALID_POINTER
);
276 return (nssASN1Decoder
*)NULL
;
280 rv
= SEC_ASN1DecoderStart(hack
, destination
, template);
281 if( (SEC_ASN1DecoderContext
*)NULL
== rv
) {
282 nss_SetError(PORT_GetError()); /* also evil */
283 return (nssASN1Decoder
*)NULL
;
287 if( PR_SUCCESS
!= decoder_add_pointer(rv
) ) {
288 (void)SEC_ASN1DecoderFinish(rv
);
289 return (nssASN1Decoder
*)NULL
;
293 return (nssASN1Decoder
*)rv
;
297 * nssASN1Decoder_Update
299 * This routine feeds data to the decoder. In the event of an error,
300 * it will place an error on the error stack and return PR_FAILURE.
302 * The error may be one of the following values:
303 * NSS_ERROR_NO_MEMORY
304 * NSS_ERROR_INVALID_POINTER
305 * NSS_ERROR_INVALID_ASN1DECODER
306 * NSS_ERROR_INVALID_BER
310 * PR_FAILURE upon error
311 * PR_SUCCESS upon success.
314 NSS_IMPLEMENT PRStatus
315 nssASN1Decoder_Update
317 nssASN1Decoder
*decoder
,
325 if( PR_SUCCESS
!= nssASN1Decoder_verify(decoder
) ) {
329 if( (void *)NULL
== data
) {
330 nss_SetError(NSS_ERROR_INVALID_POINTER
);
335 rv
= SEC_ASN1DecoderUpdate((SEC_ASN1DecoderContext
*)decoder
,
337 (unsigned long)amount
);
338 if( SECSuccess
!= rv
) {
339 nss_SetError(PORT_GetError()); /* ugly */
347 * nssASN1Decoder_Finish
349 * This routine finishes the decoding and destroys the decoder.
350 * In the event of an error, it will place an error on the error
351 * stack and return PR_FAILURE.
353 * The error may be one of the following values:
354 * NSS_ERROR_INVALID_ASN1DECODER
357 * PR_FAILURE upon error
358 * PR_SUCCESS upon success
361 NSS_IMPLEMENT PRStatus
362 nssASN1Decoder_Finish
364 nssASN1Decoder
*decoder
367 PRStatus rv
= PR_SUCCESS
;
371 if( PR_SUCCESS
!= nssASN1Decoder_verify(decoder
) ) {
376 srv
= SEC_ASN1DecoderFinish((SEC_ASN1DecoderContext
*)decoder
);
378 if( SECSuccess
!= srv
) {
379 nss_SetError(PORT_GetError()); /* ugly */
385 PRStatus rv2
= decoder_remove_pointer(decoder
);
386 if( PR_SUCCESS
== rv
) {
396 * nssASN1Decoder_SetFilter
398 * This routine registers a callback filter routine with the decoder,
399 * which will be called blah blah blah. The specified argument will
400 * be passed as-is to the filter routine. The routine pointer may
401 * be NULL, in which case no filter callback will be called. If the
402 * noStore boolean is PR_TRUE, then decoded fields will not be stored
403 * in the destination structure specified when the decoder was
404 * created. This routine returns a PRStatus value; in the event of
405 * an error, it will place an error on the error stack and return
408 * The error may be one of the following values:
409 * NSS_ERROR_INVALID_ASN1DECODER
412 * PR_FAILURE upon error
413 * PR_SUCCESS upon success
416 NSS_IMPLEMENT PRStatus
417 nssASN1Decoder_SetFilter
419 nssASN1Decoder
*decoder
,
420 nssASN1DecoderFilterFunction
*callback
,
426 if( PR_SUCCESS
!= nssASN1Decoder_verify(decoder
) ) {
431 if( (nssASN1DecoderFilterFunction
*)NULL
== callback
) {
432 SEC_ASN1DecoderClearFilterProc((SEC_ASN1DecoderContext
*)decoder
);
434 SEC_ASN1DecoderSetFilterProc((SEC_ASN1DecoderContext
*)decoder
,
435 (SEC_ASN1WriteProc
)callback
,
439 /* No error returns defined for those routines */
445 * nssASN1Decoder_GetFilter
447 * If the optional pCallbackOpt argument to this routine is non-null,
448 * then the pointer to any callback function established for this
449 * decoder with nssASN1Decoder_SetFilter will be stored at the
450 * location indicated by it. If the optional pArgumentOpt
451 * pointer is non-null, the filter's closure argument will be stored
452 * there. If the optional pNoStoreOpt pointer is non-null, the
453 * noStore value specified when setting the filter will be stored
454 * there. This routine returns a PRStatus value; in the event of
455 * an error it will place an error on the error stack and return
458 * The error may be one of the following values:
459 * NSS_ERROR_INVALID_ASN1DECODER
462 * PR_FAILURE upon error
463 * PR_SUCCESS upon success
466 extern const NSSError NSS_ERROR_INTERNAL_ERROR
;
468 NSS_IMPLEMENT PRStatus
469 nssASN1Decoder_GetFilter
471 nssASN1Decoder
*decoder
,
472 nssASN1DecoderFilterFunction
**pCallbackOpt
,
478 if( PR_SUCCESS
!= nssASN1Decoder_verify(decoder
) ) {
483 if( (nssASN1DecoderFilterFunction
**)NULL
!= pCallbackOpt
) {
484 *pCallbackOpt
= (nssASN1DecoderFilterFunction
*)NULL
;
487 if( (void **)NULL
!= pArgumentOpt
) {
488 *pArgumentOpt
= (void *)NULL
;
491 if( (PRBool
*)NULL
!= pNoStoreOpt
) {
492 *pNoStoreOpt
= PR_FALSE
;
495 /* Error because it's unimplemented */
496 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
501 * nssASN1Decoder_SetNotify
503 * This routine registers a callback notify routine with the decoder,
504 * which will be called whenever.. The specified argument will be
505 * passed as-is to the notify routine. The routine pointer may be
506 * NULL, in which case no notify routine will be called. This routine
507 * returns a PRStatus value; in the event of an error it will place
508 * an error on the error stack and return PR_FAILURE.
510 * The error may be one of the following values:
511 * NSS_ERROR_INVALID_ASN1DECODER
514 * PR_FAILURE upon error
515 * PR_SUCCESS upon success
518 NSS_IMPLEMENT PRStatus
519 nssASN1Decoder_SetNotify
521 nssASN1Decoder
*decoder
,
522 nssASN1NotifyFunction
*callback
,
527 if( PR_SUCCESS
!= nssASN1Decoder_verify(decoder
) ) {
532 if( (nssASN1NotifyFunction
*)NULL
== callback
) {
533 SEC_ASN1DecoderClearNotifyProc((SEC_ASN1DecoderContext
*)decoder
);
535 SEC_ASN1DecoderSetNotifyProc((SEC_ASN1DecoderContext
*)decoder
,
536 (SEC_ASN1NotifyProc
)callback
,
540 /* No error returns defined for those routines */
546 * nssASN1Decoder_GetNotify
548 * If the optional pCallbackOpt argument to this routine is non-null,
549 * then the pointer to any callback function established for this
550 * decoder with nssASN1Decoder_SetNotify will be stored at the
551 * location indicated by it. If the optional pArgumentOpt pointer is
552 * non-null, the filter's closure argument will be stored there.
553 * This routine returns a PRStatus value; in the event of an error it
554 * will place an error on the error stack and return PR_FAILURE.
556 * The error may be one of the following values:
557 * NSS_ERROR_INVALID_ASN1DECODER
560 * PR_FAILURE upon error
561 * PR_SUCCESS upon success
564 NSS_IMPLEMENT PRStatus
565 nssASN1Decoder_GetNotify
567 nssASN1Decoder
*decoder
,
568 nssASN1NotifyFunction
**pCallbackOpt
,
573 if( PR_SUCCESS
!= nssASN1Decoder_verify(decoder
) ) {
578 if( (nssASN1NotifyFunction
**)NULL
!= pCallbackOpt
) {
579 *pCallbackOpt
= (nssASN1NotifyFunction
*)NULL
;
582 if( (void **)NULL
!= pArgumentOpt
) {
583 *pArgumentOpt
= (void *)NULL
;
586 /* Error because it's unimplemented */
587 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
594 * This routine will decode the specified data into the specified
595 * destination structure, as specified by the specified template.
596 * This routine returns a PRStatus value; in the event of an error
597 * it will place an error on the error stack and return PR_FAILURE.
599 * The error may be one of the following values:
600 * NSS_ERROR_NO_MEMORY
601 * NSS_ERROR_INVALID_ARENA
602 * NSS_ERROR_INVALID_POINTER
603 * NSS_ERROR_INVALID_BER
606 * PR_FAILURE upon error
607 * PR_SUCCESS upon success
610 NSS_IMPLEMENT PRStatus
615 const nssASN1Template
template[],
621 nssASN1Decoder
*decoder
;
623 /* This call will do our pointer-checking for us! */
624 decoder
= nssASN1Decoder_Create(arenaOpt
, destination
, template);
625 if( (nssASN1Decoder
*)NULL
== decoder
) {
629 rv
= nssASN1Decoder_Update(decoder
, berData
, amount
);
630 if( PR_SUCCESS
!= nssASN1Decoder_Finish(decoder
) ) {
640 * This routine will decode the data in the specified NSSBER
641 * into the destination structure, as specified by the template.
642 * This routine returns a PRStatus value; in the event of an error
643 * it will place an error on the error stack and return PR_FAILURE.
645 * The error may be one of the following values:
646 * NSS_ERROR_NO_MEMORY
647 * NSS_ERROR_INVALID_ARENA
648 * NSS_ERROR_INVALID_POINTER
649 * NSS_ERROR_INVALID_NSSBER
650 * NSS_ERROR_INVALID_BER
653 * PR_FAILURE upon error
654 * PR_SUCCESS upon success
657 NSS_IMPLEMENT PRStatus
662 const nssASN1Template
template[],
666 return nssASN1_Decode(arenaOpt
, destination
, template,
667 data
->data
, data
->size
);
671 * nssASN1Encoder_Create
673 * This routine creates an ASN.1 Encoder, blah blah blah. This
674 * may return NULL upon error, in which case an error will have been
675 * placed on the error stack.
677 * The error may be one of the following values:
678 * NSS_ERROR_NO_MEMORY
679 * NSS_ERROR_INVALID_ARENA
680 * NSS_ERROR_INVALID_POINTER
685 * A pointer to an ASN.1 Encoder upon success
688 NSS_IMPLEMENT nssASN1Encoder
*
689 nssASN1Encoder_Create
692 const nssASN1Template
template[],
693 NSSASN1EncodingType encoding
,
694 nssASN1EncoderWriteFunction
*sink
,
698 SEC_ASN1EncoderContext
*rv
;
701 if( (void *)NULL
== source
) {
702 nss_SetError(NSS_ERROR_INVALID_POINTER
);
703 return (nssASN1Encoder
*)NULL
;
706 if( (nssASN1Template
*)NULL
== template ) {
707 nss_SetError(NSS_ERROR_INVALID_POINTER
);
708 return (nssASN1Encoder
*)NULL
;
711 if( (nssASN1EncoderWriteFunction
*)NULL
== sink
) {
712 nss_SetError(NSS_ERROR_INVALID_POINTER
);
713 return (nssASN1Encoder
*)NULL
;
724 case NSSASN1UnknownEncoding
:
726 nss_SetError(NSS_ERROR_ENCODING_NOT_SUPPORTED
);
727 return (nssASN1Encoder
*)NULL
;
730 rv
= SEC_ASN1EncoderStart((void *)source
, template,
731 (SEC_ASN1WriteProc
)sink
, argument
);
732 if( (SEC_ASN1EncoderContext
*)NULL
== rv
) {
733 nss_SetError(PORT_GetError()); /* ugly */
734 return (nssASN1Encoder
*)NULL
;
737 if( NSSASN1DER
== encoding
) {
738 sec_ASN1EncoderSetDER(rv
);
742 if( PR_SUCCESS
!= encoder_add_pointer(rv
) ) {
743 (void)SEC_ASN1EncoderFinish(rv
);
744 return (nssASN1Encoder
*)NULL
;
748 return (nssASN1Encoder
*)rv
;
752 * nssASN1Encoder_Update
754 * The error may be one of the following values:
755 * NSS_ERROR_INVALID_ASN1ENCODER
756 * NSS_ERROR_INVALID_POINTER
759 * PR_FAILURE upon error
760 * PR_SUCCESS upon success
763 NSS_IMPLEMENT PRStatus
764 nssASN1Encoder_Update
766 nssASN1Encoder
*encoder
,
774 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
779 * Can data legitimately be NULL? If not, verify..
783 rv
= SEC_ASN1EncoderUpdate((SEC_ASN1EncoderContext
*)encoder
,
785 (unsigned long)length
);
786 if( SECSuccess
!= rv
) {
787 nss_SetError(PORT_GetError()); /* ugly */
795 * nssASN1Encoder_Finish
799 * The error may be one of the following values:
800 * NSS_ERROR_INVALID_ASN1ENCODER
803 * PR_FAILURE upon error
804 * PR_SUCCESS upon success
807 NSS_IMPLEMENT PRStatus
808 nssASN1Encoder_Finish
810 nssASN1Encoder
*encoder
816 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
821 SEC_ASN1EncoderFinish((SEC_ASN1EncoderContext
*)encoder
);
822 rv
= PR_SUCCESS
; /* no error return defined for that call */
826 PRStatus rv2
= encoder_remove_pointer(encoder
);
827 if( PR_SUCCESS
== rv
) {
837 * nssASN1Encoder_SetNotify
839 * This routine registers a callback notify routine with the encoder,
840 * which will be called whenever.. The specified argument will be
841 * passed as-is to the notify routine. The routine pointer may be
842 * NULL, in which case no notify routine will be called. This routine
843 * returns a PRStatus value; in the event of an error it will place
844 * an error on the error stack and return PR_FAILURE.
846 * The error may be one of the following values:
847 * NSS_ERROR_INVALID_ASN1DECODER
850 * PR_FAILURE upon error
851 * PR_SUCCESS upon success
854 NSS_IMPLEMENT PRStatus
855 nssASN1Encoder_SetNotify
857 nssASN1Encoder
*encoder
,
858 nssASN1NotifyFunction
*callback
,
863 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
868 if( (nssASN1NotifyFunction
*)NULL
== callback
) {
869 SEC_ASN1EncoderClearNotifyProc((SEC_ASN1EncoderContext
*)encoder
);
871 SEC_ASN1EncoderSetNotifyProc((SEC_ASN1EncoderContext
*)encoder
,
872 (SEC_ASN1NotifyProc
)callback
,
876 /* no error return defined for those routines */
882 * nssASN1Encoder_GetNotify
884 * If the optional pCallbackOpt argument to this routine is non-null,
885 * then the pointer to any callback function established for this
886 * decoder with nssASN1Encoder_SetNotify will be stored at the
887 * location indicated by it. If the optional pArgumentOpt pointer is
888 * non-null, the filter's closure argument will be stored there.
889 * This routine returns a PRStatus value; in the event of an error it
890 * will place an error on the error stack and return PR_FAILURE.
892 * The error may be one of the following values:
893 * NSS_ERROR_INVALID_ASN1ENCODER
896 * PR_FAILURE upon error
897 * PR_SUCCESS upon success
900 NSS_IMPLEMENT PRStatus
901 nssASN1Encoder_GetNotify
903 nssASN1Encoder
*encoder
,
904 nssASN1NotifyFunction
**pCallbackOpt
,
909 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
914 if( (nssASN1NotifyFunction
**)NULL
!= pCallbackOpt
) {
915 *pCallbackOpt
= (nssASN1NotifyFunction
*)NULL
;
918 if( (void **)NULL
!= pArgumentOpt
) {
919 *pArgumentOpt
= (void *)NULL
;
922 /* Error because it's unimplemented */
923 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
928 * nssASN1Encoder_SetStreaming
931 * The error may be one of the following values:
932 * NSS_ERROR_INVALID_ASN1ENCODER
935 * PR_FAILURE upon error
936 * PR_SUCCESS upon success
939 NSS_IMPLEMENT PRStatus
940 nssASN1Encoder_SetStreaming
942 nssASN1Encoder
*encoder
,
946 SEC_ASN1EncoderContext
*cx
= (SEC_ASN1EncoderContext
*)encoder
;
949 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
955 SEC_ASN1EncoderSetStreaming(cx
);
957 SEC_ASN1EncoderClearStreaming(cx
);
960 /* no error return defined for those routines */
966 * nssASN1Encoder_GetStreaming
969 * The error may be one of the following values:
970 * NSS_ERROR_INVALID_ASN1ENCODER
971 * NSS_ERROR_INVALID_POINTER
974 * PR_FAILURE upon error
975 * PR_SUCCESS upon success
979 nssASN1Encoder_GetStreaming
981 nssASN1Encoder
*encoder
,
986 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
991 if( (PRBool
*)NULL
!= pStreaming
) {
992 *pStreaming
= PR_FALSE
;
995 /* Error because it's unimplemented */
996 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
1001 * nssASN1Encoder_SetTakeFromBuffer
1004 * The error may be one of the following values:
1005 * NSS_ERROR_INVALID_ASN1ENCODER
1008 * PR_FAILURE upon error
1009 * PR_SUCCESS upon success
1012 NSS_IMPLEMENT PRStatus
1013 nssASN1Encoder_SetTakeFromBuffer
1015 nssASN1Encoder
*encoder
,
1016 PRBool takeFromBuffer
1019 SEC_ASN1EncoderContext
*cx
= (SEC_ASN1EncoderContext
*)encoder
;
1022 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
1027 if( takeFromBuffer
) {
1028 SEC_ASN1EncoderSetTakeFromBuf(cx
);
1030 SEC_ASN1EncoderClearTakeFromBuf(cx
);
1033 /* no error return defined for those routines */
1039 * nssASN1Encoder_GetTakeFromBuffer
1042 * The error may be one of the following values:
1043 * NSS_ERROR_INVALID_ASN1ENCODER
1044 * NSS_ERROR_INVALID_POINTER
1047 * PR_FAILURE upon error
1048 * PR_SUCCESS upon success
1051 NSS_IMPLEMENT PRStatus
1052 nssASN1Encoder_GetTakeFromBuffer
1054 nssASN1Encoder
*encoder
,
1055 PRBool
*pTakeFromBuffer
1059 if( PR_SUCCESS
!= nssASN1Encoder_verify(encoder
) ) {
1064 if( (PRBool
*)NULL
!= pTakeFromBuffer
) {
1065 *pTakeFromBuffer
= PR_FALSE
;
1068 /* Error because it's unimplemented */
1069 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
1077 * The error may be one of the following values:
1078 * NSS_ERROR_NO_MEMORY
1079 * NSS_ERROR_INVALID_ARENA
1080 * NSS_ERROR_INVALID_POINTER
1081 * NSS_ERROR_ENCODING_NOT_SUPPORTED
1085 * PR_FAILURE upon error
1086 * PR_SUCCESS upon success
1089 NSS_IMPLEMENT PRStatus
1093 const nssASN1Template
template[],
1094 NSSASN1EncodingType encoding
,
1095 nssASN1EncoderWriteFunction
*sink
,
1100 nssASN1Encoder
*encoder
;
1102 encoder
= nssASN1Encoder_Create(source
, template, encoding
, sink
, argument
);
1103 if( (nssASN1Encoder
*)NULL
== encoder
) {
1107 rv
= nssASN1Encoder_Update(encoder
, (const void *)NULL
, 0);
1108 if( PR_SUCCESS
!= nssASN1Encoder_Finish(encoder
) ) {
1116 * nssasn1_encode_item_count
1118 * This is a helper function for nssASN1_EncodeItem. It just counts
1119 * up the space required for an encoding.
1123 nssasn1_encode_item_count
1129 nssASN1EncodingPart data_kind
1132 unsigned long *count
;
1134 count
= (unsigned long*)arg
;
1135 PR_ASSERT (count
!= NULL
);
1141 * nssasn1_encode_item_store
1143 * This is a helper function for nssASN1_EncodeItem. It appends the
1144 * new data onto the destination item.
1148 nssasn1_encode_item_store
1154 nssASN1EncodingPart data_kind
1159 dest
= (NSSItem
*)arg
;
1160 PR_ASSERT (dest
!= NULL
);
1162 memcpy((unsigned char *)dest
->data
+ dest
->size
, buf
, len
);
1167 * nssASN1_EncodeItem
1169 * There must be a better name. If the optional arena argument is
1170 * non-null, it'll be used for the space. If the optional rvOpt is
1171 * non-null, it'll be the return value-- if it is null, a new one
1172 * will be allocated.
1174 * The error may be one of the following values:
1175 * NSS_ERROR_NO_MEMORY
1176 * NSS_ERROR_INVALID_ARENA
1177 * NSS_ERROR_INVALID_POINTER
1178 * NSS_ERROR_ENCODING_NOT_SUPPORTED
1182 * A valid pointer to an NSSDER upon success
1185 NSS_IMPLEMENT NSSDER
*
1191 const nssASN1Template
template[],
1192 NSSASN1EncodingType encoding
1200 if( (NSSArena
*)NULL
!= arenaOpt
) {
1201 if( PR_SUCCESS
!= nssArena_verifyPointer(arenaOpt
) ) {
1202 return (NSSDER
*)NULL
;
1206 if( (void *)NULL
== source
) {
1207 nss_SetError(NSS_ERROR_INVALID_POINTER
);
1208 return (NSSDER
*)NULL
;
1211 if( (nssASN1Template
*)NULL
== template ) {
1212 nss_SetError(NSS_ERROR_INVALID_POINTER
);
1213 return (NSSDER
*)NULL
;
1217 status
= nssASN1_Encode(source
, template, encoding
,
1218 (nssASN1EncoderWriteFunction
*)nssasn1_encode_item_count
,
1220 if( PR_SUCCESS
!= status
) {
1221 return (NSSDER
*)NULL
;
1224 if( (NSSDER
*)NULL
== rvOpt
) {
1225 rv
= nss_ZNEW(arenaOpt
, NSSDER
);
1226 if( (NSSDER
*)NULL
== rv
) {
1227 return (NSSDER
*)NULL
;
1234 rv
->data
= nss_ZAlloc(arenaOpt
, len
);
1235 if( (void *)NULL
== rv
->data
) {
1236 if( (NSSDER
*)NULL
== rvOpt
) {
1239 return (NSSDER
*)NULL
;
1242 rv
->size
= 0; /* for nssasn1_encode_item_store */
1244 status
= nssASN1_Encode(source
, template, encoding
,
1245 (nssASN1EncoderWriteFunction
*)nssasn1_encode_item_store
,
1247 if( PR_SUCCESS
!= status
) {
1248 nss_ZFreeIf(rv
->data
);
1249 if( (NSSDER
*)NULL
== rvOpt
) {
1252 return (NSSDER
*)NULL
;
1255 PR_ASSERT(rv
->size
== len
);
1261 * nssASN1_CreatePRUint32FromBER
1265 NSS_IMPLEMENT PRStatus
1266 nssASN1_CreatePRUint32FromBER
1272 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
1277 * nssASN1_GetDERFromPRUint32
1282 nssASN1_GetDERFromPRUint32
1290 PLArenaPool
*hack
= (PLArenaPool
*)arenaOpt
;
1294 if( (NSSArena
*)NULL
!= arenaOpt
) {
1295 if( PR_SUCCESS
!= nssArena_verifyPointer(arenaOpt
) ) {
1296 return (NSSDER
*)NULL
;
1301 if( (NSSDER
*)NULL
== rvOpt
) {
1302 rv
= nss_ZNEW(arenaOpt
, NSSDER
);
1303 if( (NSSDER
*)NULL
== rv
) {
1304 return (NSSDER
*)NULL
;
1310 item
= SEC_ASN1EncodeUnsignedInteger(hack
, (SECItem
*)rv
, value
);
1311 if( (SECItem
*)NULL
== item
) {
1312 if( (NSSDER
*)NULL
== rvOpt
) {
1313 (void)nss_ZFreeIf(rv
);
1316 nss_SetError(PORT_GetError()); /* ugly */
1317 return (NSSDER
*)NULL
;
1321 * I happen to know that these things look alike.. but I'm only
1322 * doing it for these "temporary" wrappers. This is an evil thing.
1324 return (NSSDER
*)item
;
1328 NSS_IMPLEMENT PRStatus
1329 nssASN1_CreatePRInt32FromBER
1335 nss_SetError(NSS_ERROR_INTERNAL_ERROR
);
1340 * nssASN1_GetDERFromPRInt32
1344 NSS_IMPLEMENT NSSDER
*
1345 nssASN1_GetDERFromPRInt32
1353 PLArenaPool
*hack
= (PLArenaPool
*)arenaOpt
;
1357 if( (NSSArena
*)NULL
!= arenaOpt
) {
1358 if( PR_SUCCESS
!= nssArena_verifyPointer(arenaOpt
) ) {
1359 return (NSSDER
*)NULL
;
1364 if( (NSSDER
*)NULL
== rvOpt
) {
1365 rv
= nss_ZNEW(arenaOpt
, NSSDER
);
1366 if( (NSSDER
*)NULL
== rv
) {
1367 return (NSSDER
*)NULL
;
1373 item
= SEC_ASN1EncodeInteger(hack
, (SECItem
*)rv
, value
);
1374 if( (SECItem
*)NULL
== item
) {
1375 if( (NSSDER
*)NULL
== rvOpt
) {
1376 (void)nss_ZFreeIf(rv
);
1379 nss_SetError(PORT_GetError()); /* ugly */
1380 return (NSSDER
*)NULL
;
1384 * I happen to know that these things look alike.. but I'm only
1385 * doing it for these "temporary" wrappers. This is an evil thing.
1387 return (NSSDER
*)item
;
1392 * One for each of the simple types, plus a special one for ANY, plus:
1393 * - a pointer to each one of those
1394 * - a set of each one of those
1396 * Note that these are alphabetical (case insensitive); please add new
1397 * ones in the appropriate place.
1400 const nssASN1Template
*nssASN1Template_Any
= (nssASN1Template
*)SEC_AnyTemplate
;
1401 const nssASN1Template
*nssASN1Template_BitString
= (nssASN1Template
*)SEC_BitStringTemplate
;
1402 const nssASN1Template
*nssASN1Template_BMPString
= (nssASN1Template
*)SEC_BMPStringTemplate
;
1403 const nssASN1Template
*nssASN1Template_Boolean
= (nssASN1Template
*)SEC_BooleanTemplate
;
1404 const nssASN1Template
*nssASN1Template_Enumerated
= (nssASN1Template
*)SEC_EnumeratedTemplate
;
1405 const nssASN1Template
*nssASN1Template_GeneralizedTime
= (nssASN1Template
*)SEC_GeneralizedTimeTemplate
;
1406 const nssASN1Template
*nssASN1Template_IA5String
= (nssASN1Template
*)SEC_IA5StringTemplate
;
1407 const nssASN1Template
*nssASN1Template_Integer
= (nssASN1Template
*)SEC_IntegerTemplate
;
1408 const nssASN1Template
*nssASN1Template_Null
= (nssASN1Template
*)SEC_NullTemplate
;
1409 const nssASN1Template
*nssASN1Template_ObjectID
= (nssASN1Template
*)SEC_ObjectIDTemplate
;
1410 const nssASN1Template
*nssASN1Template_OctetString
= (nssASN1Template
*)SEC_OctetStringTemplate
;
1411 const nssASN1Template
*nssASN1Template_PrintableString
= (nssASN1Template
*)SEC_PrintableStringTemplate
;
1412 const nssASN1Template
*nssASN1Template_T61String
= (nssASN1Template
*)SEC_T61StringTemplate
;
1413 const nssASN1Template
*nssASN1Template_UniversalString
= (nssASN1Template
*)SEC_UniversalStringTemplate
;
1414 const nssASN1Template
*nssASN1Template_UTCTime
= (nssASN1Template
*)SEC_UTCTimeTemplate
;
1415 const nssASN1Template
*nssASN1Template_UTF8String
= (nssASN1Template
*)SEC_UTF8StringTemplate
;
1416 const nssASN1Template
*nssASN1Template_VisibleString
= (nssASN1Template
*)SEC_VisibleStringTemplate
;
1418 const nssASN1Template
*nssASN1Template_PointerToAny
= (nssASN1Template
*)SEC_PointerToAnyTemplate
;
1419 const nssASN1Template
*nssASN1Template_PointerToBitString
= (nssASN1Template
*)SEC_PointerToBitStringTemplate
;
1420 const nssASN1Template
*nssASN1Template_PointerToBMPString
= (nssASN1Template
*)SEC_PointerToBMPStringTemplate
;
1421 const nssASN1Template
*nssASN1Template_PointerToBoolean
= (nssASN1Template
*)SEC_PointerToBooleanTemplate
;
1422 const nssASN1Template
*nssASN1Template_PointerToEnumerated
= (nssASN1Template
*)SEC_PointerToEnumeratedTemplate
;
1423 const nssASN1Template
*nssASN1Template_PointerToGeneralizedTime
= (nssASN1Template
*)SEC_PointerToGeneralizedTimeTemplate
;
1424 const nssASN1Template
*nssASN1Template_PointerToIA5String
= (nssASN1Template
*)SEC_PointerToIA5StringTemplate
;
1425 const nssASN1Template
*nssASN1Template_PointerToInteger
= (nssASN1Template
*)SEC_PointerToIntegerTemplate
;
1426 const nssASN1Template
*nssASN1Template_PointerToNull
= (nssASN1Template
*)SEC_PointerToNullTemplate
;
1427 const nssASN1Template
*nssASN1Template_PointerToObjectID
= (nssASN1Template
*)SEC_PointerToObjectIDTemplate
;
1428 const nssASN1Template
*nssASN1Template_PointerToOctetString
= (nssASN1Template
*)SEC_PointerToOctetStringTemplate
;
1429 const nssASN1Template
*nssASN1Template_PointerToPrintableString
= (nssASN1Template
*)SEC_PointerToPrintableStringTemplate
;
1430 const nssASN1Template
*nssASN1Template_PointerToT61String
= (nssASN1Template
*)SEC_PointerToT61StringTemplate
;
1431 const nssASN1Template
*nssASN1Template_PointerToUniversalString
= (nssASN1Template
*)SEC_PointerToUniversalStringTemplate
;
1432 const nssASN1Template
*nssASN1Template_PointerToUTCTime
= (nssASN1Template
*)SEC_PointerToUTCTimeTemplate
;
1433 const nssASN1Template
*nssASN1Template_PointerToUTF8String
= (nssASN1Template
*)SEC_PointerToUTF8StringTemplate
;
1434 const nssASN1Template
*nssASN1Template_PointerToVisibleString
= (nssASN1Template
*)SEC_PointerToVisibleStringTemplate
;
1436 const nssASN1Template
*nssASN1Template_SetOfAny
= (nssASN1Template
*)SEC_SetOfAnyTemplate
;
1437 const nssASN1Template
*nssASN1Template_SetOfBitString
= (nssASN1Template
*)SEC_SetOfBitStringTemplate
;
1438 const nssASN1Template
*nssASN1Template_SetOfBMPString
= (nssASN1Template
*)SEC_SetOfBMPStringTemplate
;
1439 const nssASN1Template
*nssASN1Template_SetOfBoolean
= (nssASN1Template
*)SEC_SetOfBooleanTemplate
;
1440 const nssASN1Template
*nssASN1Template_SetOfEnumerated
= (nssASN1Template
*)SEC_SetOfEnumeratedTemplate
;
1441 const nssASN1Template
*nssASN1Template_SetOfGeneralizedTime
= (nssASN1Template
*)SEC_SetOfGeneralizedTimeTemplate
;
1442 const nssASN1Template
*nssASN1Template_SetOfIA5String
= (nssASN1Template
*)SEC_SetOfIA5StringTemplate
;
1443 const nssASN1Template
*nssASN1Template_SetOfInteger
= (nssASN1Template
*)SEC_SetOfIntegerTemplate
;
1444 const nssASN1Template
*nssASN1Template_SetOfNull
= (nssASN1Template
*)SEC_SetOfNullTemplate
;
1445 const nssASN1Template
*nssASN1Template_SetOfObjectID
= (nssASN1Template
*)SEC_SetOfObjectIDTemplate
;
1446 const nssASN1Template
*nssASN1Template_SetOfOctetString
= (nssASN1Template
*)SEC_SetOfOctetStringTemplate
;
1447 const nssASN1Template
*nssASN1Template_SetOfPrintableString
= (nssASN1Template
*)SEC_SetOfPrintableStringTemplate
;
1448 const nssASN1Template
*nssASN1Template_SetOfT61String
= (nssASN1Template
*)SEC_SetOfT61StringTemplate
;
1449 const nssASN1Template
*nssASN1Template_SetOfUniversalString
= (nssASN1Template
*)SEC_SetOfUniversalStringTemplate
;
1450 const nssASN1Template
*nssASN1Template_SetOfUTCTime
= (nssASN1Template
*)SEC_SetOfUTCTimeTemplate
;
1451 const nssASN1Template
*nssASN1Template_SetOfUTF8String
= (nssASN1Template
*)SEC_SetOfUTF8StringTemplate
;
1452 const nssASN1Template
*nssASN1Template_SetOfVisibleString
= (nssASN1Template
*)SEC_SetOfVisibleStringTemplate
;
1458 NSS_IMPLEMENT NSSUTF8
*
1459 nssUTF8_CreateFromBER
1472 const nssASN1Template
*templ
;
1475 if( (NSSArena
*)NULL
!= arenaOpt
) {
1476 if( PR_SUCCESS
!= nssArena_verifyPointer(arenaOpt
) ) {
1477 return (NSSUTF8
*)NULL
;
1481 if( (NSSBER
*)NULL
== berData
) {
1482 nss_SetError(NSS_ERROR_INVALID_POINTER
);
1483 return (NSSUTF8
*)NULL
;
1486 if( (void *)NULL
== berData
->data
) {
1487 nss_SetError(NSS_ERROR_INVALID_POINTER
);
1488 return (NSSUTF8
*)NULL
;
1490 #endif /* NSSDEBUG */
1492 a
= NSSArena_Create();
1493 if( (NSSArena
*)NULL
== a
) {
1494 return (NSSUTF8
*)NULL
;
1500 * By the way, at first I succumbed to the temptation to make
1501 * this an incestuous nested switch statement. Count yourself
1502 * lucky I cleaned it up.
1506 case nssStringType_DirectoryString
:
1508 * draft-ietf-pkix-ipki-part1-11 says in part:
1510 * DirectoryString { INTEGER:maxSize } ::= CHOICE {
1511 * teletexString TeletexString (SIZE (1..maxSize)),
1512 * printableString PrintableString (SIZE (1..maxSize)),
1513 * universalString UniversalString (SIZE (1..maxSize)),
1514 * bmpString BMPString (SIZE(1..maxSize)),
1515 * utf8String UTF8String (SIZE(1..maxSize))
1519 * TeletexString UNIVERSAL 20
1520 * PrintableString UNIVERSAL 19
1521 * UniversalString UNIVERSAL 28
1522 * BMPString UNIVERSAL 30
1523 * UTF8String UNIVERSAL 12
1525 * "UNIVERSAL" tags have bits 8 and 7 zero, bit 6 is zero for
1526 * primitive encodings, and if the tag value is less than 30,
1527 * the tag value is directly encoded in bits 5 through 1.
1529 in
.data
= (void *)&(((PRUint8
*)berData
->data
)[1]);
1530 in
.size
= berData
->size
-1;
1532 tag
= *(PRUint8
*)berData
->data
;
1533 switch( tag
& nssASN1_TAGNUM_MASK
) {
1536 * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
1537 * below) but is T61 a suitable value for "Latin-1"?
1539 templ
= nssASN1Template_T61String
;
1540 type
= nssStringType_TeletexString
;
1543 templ
= nssASN1Template_PrintableString
;
1544 type
= nssStringType_PrintableString
;
1547 templ
= nssASN1Template_UniversalString
;
1548 type
= nssStringType_UniversalString
;
1551 templ
= nssASN1Template_BMPString
;
1552 type
= nssStringType_BMPString
;
1555 templ
= nssASN1Template_UTF8String
;
1556 type
= nssStringType_UTF8String
;
1559 nss_SetError(NSS_ERROR_INVALID_POINTER
); /* "pointer"? */
1560 (void)NSSArena_Destroy(a
);
1561 return (NSSUTF8
*)NULL
;
1566 case nssStringType_TeletexString
:
1568 * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
1569 * below) but is T61 a suitable value for "Latin-1"?
1571 templ
= nssASN1Template_T61String
;
1574 case nssStringType_PrintableString
:
1575 templ
= nssASN1Template_PrintableString
;
1578 case nssStringType_UniversalString
:
1579 templ
= nssASN1Template_UniversalString
;
1582 case nssStringType_BMPString
:
1583 templ
= nssASN1Template_BMPString
;
1586 case nssStringType_UTF8String
:
1587 templ
= nssASN1Template_UTF8String
;
1590 case nssStringType_PHGString
:
1591 templ
= nssASN1Template_IA5String
;
1595 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE
);
1596 (void)NSSArena_Destroy(a
);
1597 return (NSSUTF8
*)NULL
;
1600 st
= nssASN1_DecodeBER(a
, &out
, templ
, &in
);
1602 if( PR_SUCCESS
== st
) {
1603 rv
= nssUTF8_Create(arenaOpt
, type
, out
.data
, out
.size
);
1605 (void)NSSArena_Destroy(a
);
1611 nssUTF8_GetDEREncoding
1615 const NSSUTF8
*string
1618 NSSDER
*rv
= (NSSDER
*)NULL
;
1621 const nssASN1Template
*templ
;
1625 if( (NSSArena
*)NULL
!= arenaOpt
) {
1626 if( PR_SUCCESS
!= nssArena_verifyPointer(arenaOpt
) ) {
1627 return (NSSDER
*)NULL
;
1631 if( (const NSSUTF8
*)NULL
== string
) {
1632 nss_SetError(NSS_ERROR_INVALID_POINTER
);
1633 return (NSSDER
*)NULL
;
1635 #endif /* NSSDEBUG */
1637 str
.data
= (void *)string
;
1638 str
.size
= nssUTF8_Size(string
, (PRStatus
*)NULL
);
1639 if( 0 == str
.size
) {
1640 return (NSSDER
*)NULL
;
1643 a
= NSSArena_Create();
1644 if( (NSSArena
*)NULL
== a
) {
1645 return (NSSDER
*)NULL
;
1649 case nssStringType_DirectoryString
:
1654 utf
= nssASN1_EncodeItem(a
, (NSSDER
*)NULL
, &str
,
1655 nssASN1Template_UTF8String
,
1657 if( (NSSDER
*)NULL
== utf
) {
1658 (void)NSSArena_Destroy(a
);
1659 return (NSSDER
*)NULL
;
1662 rv
= nss_ZNEW(arenaOpt
, NSSDER
);
1663 if( (NSSDER
*)NULL
== rv
) {
1664 (void)NSSArena_Destroy(a
);
1665 return (NSSDER
*)NULL
;
1668 rv
->size
= utf
->size
+ 1;
1669 rv
->data
= nss_ZAlloc(arenaOpt
, rv
->size
);
1670 if( (void *)NULL
== rv
->data
) {
1671 (void)nss_ZFreeIf(rv
);
1672 (void)NSSArena_Destroy(a
);
1673 return (NSSDER
*)NULL
;
1676 c
= (PRUint8
*)rv
->data
;
1677 (void)nsslibc_memcpy(&c
[1], utf
->data
, utf
->size
);
1678 *c
= 12; /* UNIVERSAL primitive encoding tag for UTF8String */
1680 (void)NSSArena_Destroy(a
);
1683 case nssStringType_TeletexString
:
1685 * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
1686 * below) but is T61 a suitable value for "Latin-1"?
1688 templ
= nssASN1Template_T61String
;
1690 case nssStringType_PrintableString
:
1691 templ
= nssASN1Template_PrintableString
;
1694 case nssStringType_UniversalString
:
1695 templ
= nssASN1Template_UniversalString
;
1698 case nssStringType_BMPString
:
1699 templ
= nssASN1Template_BMPString
;
1702 case nssStringType_UTF8String
:
1703 templ
= nssASN1Template_UTF8String
;
1706 case nssStringType_PHGString
:
1707 templ
= nssASN1Template_IA5String
;
1711 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE
);
1712 (void)NSSArena_Destroy(a
);
1713 return (NSSDER
*)NULL
;
1716 der
= nssUTF8_GetDEREncoding(a
, type
, string
);
1717 if( (NSSItem
*)NULL
== der
) {
1718 (void)NSSArena_Destroy(a
);
1719 return (NSSDER
*)NULL
;
1722 rv
= nssASN1_EncodeItem(arenaOpt
, (NSSDER
*)NULL
, der
, templ
, NSSASN1DER
);
1723 if( (NSSDER
*)NULL
== rv
) {
1724 (void)NSSArena_Destroy(a
);
1725 return (NSSDER
*)NULL
;
1728 (void)NSSArena_Destroy(a
);