Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / asn1 / asn1.c
blobd8e9726a469d5cb188680b2e05eee64af155412e
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
12 * License.
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.
21 * Contributor(s):
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 ***** */
37 #ifdef DEBUG
38 static const char CVS_ID[] = "@(#) $RCSfile: asn1.c,v $ $Revision: 1.4 $ $Date: 2005/01/20 02:25:44 $";
39 #endif /* DEBUG */
42 * asn1.c
44 * At this point in time, this file contains the NSS wrappers for
45 * the old "SEC" ASN.1 encoder/decoder stuff.
48 #ifndef ASN1M_H
49 #include "asn1m.h"
50 #endif /* ASN1M_H */
52 #include "plarena.h"
53 #include "secasn1.h"
56 * The pointer-tracking stuff
59 #ifdef DEBUG
60 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
62 static nssPointerTracker decoder_pointer_tracker;
64 static PRStatus
65 decoder_add_pointer
67 const nssASN1Decoder *decoder
70 PRStatus rv;
72 rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
73 if( PR_SUCCESS != rv ) {
74 return 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);
84 return rv;
87 return PR_SUCCESS;
90 static PRStatus
91 decoder_remove_pointer
93 const nssASN1Decoder *decoder
96 PRStatus rv;
98 rv = nssPointerTracker_remove(&decoder_pointer_tracker, decoder);
99 if( PR_SUCCESS != rv ) {
100 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
103 return rv;
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
118 * Return value:
119 * PR_FAILURE upon error
120 * PR_SUCCESS upon success
123 NSS_IMPLEMENT PRStatus
124 nssASN1Decoder_verify
126 nssASN1Decoder *decoder
129 PRStatus rv;
131 rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
132 if( PR_SUCCESS != rv ) {
133 return PR_FAILURE;
136 rv = nssPointerTracker_verify(&decoder_pointer_tracker, decoder);
137 if( PR_SUCCESS != rv ) {
138 nss_SetError(NSS_ERROR_INVALID_ASN1DECODER);
139 return PR_FAILURE;
142 return PR_SUCCESS;
145 static nssPointerTracker encoder_pointer_tracker;
147 static PRStatus
148 encoder_add_pointer
150 const nssASN1Encoder *encoder
153 PRStatus rv;
155 rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
156 if( PR_SUCCESS != rv ) {
157 return 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);
167 return rv;
170 return PR_SUCCESS;
173 static PRStatus
174 encoder_remove_pointer
176 const nssASN1Encoder *encoder
179 PRStatus rv;
181 rv = nssPointerTracker_remove(&encoder_pointer_tracker, encoder);
182 if( PR_SUCCESS != rv ) {
183 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
186 return rv;
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
201 * Return value:
202 * PR_FAILURE upon error
203 * PR_SUCCESS upon success
206 NSS_IMPLEMENT PRStatus
207 nssASN1Encoder_verify
209 nssASN1Encoder *encoder
212 PRStatus rv;
214 rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
215 if( PR_SUCCESS != rv ) {
216 return PR_FAILURE;
219 rv = nssPointerTracker_verify(&encoder_pointer_tracker, encoder);
220 if( PR_SUCCESS != rv ) {
221 nss_SetError(NSS_ERROR_INVALID_ASN1ENCODER);
222 return PR_FAILURE;
225 return PR_SUCCESS;
227 #endif /* DEBUG */
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
244 * ...
246 * Return value:
247 * NULL upon error
248 * A pointer to an ASN.1 Decoder upon success.
251 NSS_IMPLEMENT nssASN1Decoder *
252 nssASN1Decoder_Create
254 NSSArena *arenaOpt,
255 void *destination,
256 const nssASN1Template template[]
259 SEC_ASN1DecoderContext *rv;
260 PLArenaPool *hack = (PLArenaPool *)arenaOpt;
262 #ifdef DEBUG
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;
278 #endif /* DEBUG */
280 rv = SEC_ASN1DecoderStart(hack, destination, template);
281 if( (SEC_ASN1DecoderContext *)NULL == rv ) {
282 nss_SetError(PORT_GetError()); /* also evil */
283 return (nssASN1Decoder *)NULL;
286 #ifdef DEBUG
287 if( PR_SUCCESS != decoder_add_pointer(rv) ) {
288 (void)SEC_ASN1DecoderFinish(rv);
289 return (nssASN1Decoder *)NULL;
291 #endif /* DEBUG */
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
307 * ...
309 * Return value:
310 * PR_FAILURE upon error
311 * PR_SUCCESS upon success.
314 NSS_IMPLEMENT PRStatus
315 nssASN1Decoder_Update
317 nssASN1Decoder *decoder,
318 const void *data,
319 PRUint32 amount
322 SECStatus rv;
324 #ifdef DEBUG
325 if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
326 return PR_FAILURE;
329 if( (void *)NULL == data ) {
330 nss_SetError(NSS_ERROR_INVALID_POINTER);
331 return PR_FAILURE;
333 #endif /* DEBUG */
335 rv = SEC_ASN1DecoderUpdate((SEC_ASN1DecoderContext *)decoder,
336 (const char *)data,
337 (unsigned long)amount);
338 if( SECSuccess != rv ) {
339 nss_SetError(PORT_GetError()); /* ugly */
340 return PR_FAILURE;
343 return PR_SUCCESS;
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
356 * Return value:
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;
368 SECStatus srv;
370 #ifdef DEBUG
371 if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
372 return PR_FAILURE;
374 #endif /* DEBUG */
376 srv = SEC_ASN1DecoderFinish((SEC_ASN1DecoderContext *)decoder);
378 if( SECSuccess != srv ) {
379 nss_SetError(PORT_GetError()); /* ugly */
380 rv = PR_FAILURE;
383 #ifdef DEBUG
385 PRStatus rv2 = decoder_remove_pointer(decoder);
386 if( PR_SUCCESS == rv ) {
387 rv = rv2;
390 #endif /* DEBUG */
392 return 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
406 * PR_FAILURE.
408 * The error may be one of the following values:
409 * NSS_ERROR_INVALID_ASN1DECODER
411 * Return value:
412 * PR_FAILURE upon error
413 * PR_SUCCESS upon success
416 NSS_IMPLEMENT PRStatus
417 nssASN1Decoder_SetFilter
419 nssASN1Decoder *decoder,
420 nssASN1DecoderFilterFunction *callback,
421 void *argument,
422 PRBool noStore
425 #ifdef DEBUG
426 if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
427 return PR_FAILURE;
429 #endif /* DEBUG */
431 if( (nssASN1DecoderFilterFunction *)NULL == callback ) {
432 SEC_ASN1DecoderClearFilterProc((SEC_ASN1DecoderContext *)decoder);
433 } else {
434 SEC_ASN1DecoderSetFilterProc((SEC_ASN1DecoderContext *)decoder,
435 (SEC_ASN1WriteProc)callback,
436 argument, noStore);
439 /* No error returns defined for those routines */
441 return PR_SUCCESS;
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
456 * PR_FAILURE.
458 * The error may be one of the following values:
459 * NSS_ERROR_INVALID_ASN1DECODER
461 * Return value:
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,
473 void **pArgumentOpt,
474 PRBool *pNoStoreOpt
477 #ifdef DEBUG
478 if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
479 return PR_FAILURE;
481 #endif /* DEBUG */
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);
497 return PR_FAILURE;
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
513 * Return value:
514 * PR_FAILURE upon error
515 * PR_SUCCESS upon success
518 NSS_IMPLEMENT PRStatus
519 nssASN1Decoder_SetNotify
521 nssASN1Decoder *decoder,
522 nssASN1NotifyFunction *callback,
523 void *argument
526 #ifdef DEBUG
527 if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
528 return PR_FAILURE;
530 #endif /* DEBUG */
532 if( (nssASN1NotifyFunction *)NULL == callback ) {
533 SEC_ASN1DecoderClearNotifyProc((SEC_ASN1DecoderContext *)decoder);
534 } else {
535 SEC_ASN1DecoderSetNotifyProc((SEC_ASN1DecoderContext *)decoder,
536 (SEC_ASN1NotifyProc)callback,
537 argument);
540 /* No error returns defined for those routines */
542 return PR_SUCCESS;
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
559 * Return value:
560 * PR_FAILURE upon error
561 * PR_SUCCESS upon success
564 NSS_IMPLEMENT PRStatus
565 nssASN1Decoder_GetNotify
567 nssASN1Decoder *decoder,
568 nssASN1NotifyFunction **pCallbackOpt,
569 void **pArgumentOpt
572 #ifdef DEBUG
573 if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
574 return PR_FAILURE;
576 #endif /* DEBUG */
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);
588 return PR_FAILURE;
592 * nssASN1_Decode
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
605 * Return value:
606 * PR_FAILURE upon error
607 * PR_SUCCESS upon success
610 NSS_IMPLEMENT PRStatus
611 nssASN1_Decode
613 NSSArena *arenaOpt,
614 void *destination,
615 const nssASN1Template template[],
616 const void *berData,
617 PRUint32 amount
620 PRStatus rv;
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 ) {
626 return PR_FAILURE;
629 rv = nssASN1Decoder_Update(decoder, berData, amount);
630 if( PR_SUCCESS != nssASN1Decoder_Finish(decoder) ) {
631 rv = PR_FAILURE;
634 return rv;
638 * nssASN1_DecodeBER
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
652 * Return value:
653 * PR_FAILURE upon error
654 * PR_SUCCESS upon success
657 NSS_IMPLEMENT PRStatus
658 nssASN1_DecodeBER
660 NSSArena *arenaOpt,
661 void *destination,
662 const nssASN1Template template[],
663 const NSSBER *data
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
681 * ...
683 * Return value:
684 * NULL upon error
685 * A pointer to an ASN.1 Encoder upon success
688 NSS_IMPLEMENT nssASN1Encoder *
689 nssASN1Encoder_Create
691 const void *source,
692 const nssASN1Template template[],
693 NSSASN1EncodingType encoding,
694 nssASN1EncoderWriteFunction *sink,
695 void *argument
698 SEC_ASN1EncoderContext *rv;
700 #ifdef DEBUG
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;
715 #endif /* DEBUG */
717 switch( encoding ) {
718 case NSSASN1BER:
719 case NSSASN1DER:
720 break;
721 case NSSASN1CER:
722 case NSSASN1LWER:
723 case NSSASN1PER:
724 case NSSASN1UnknownEncoding:
725 default:
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);
741 #ifdef DEBUG
742 if( PR_SUCCESS != encoder_add_pointer(rv) ) {
743 (void)SEC_ASN1EncoderFinish(rv);
744 return (nssASN1Encoder *)NULL;
746 #endif /* DEBUG */
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
758 * Return value:
759 * PR_FAILURE upon error
760 * PR_SUCCESS upon success
763 NSS_IMPLEMENT PRStatus
764 nssASN1Encoder_Update
766 nssASN1Encoder *encoder,
767 const void *data,
768 PRUint32 length
771 SECStatus rv;
773 #ifdef DEBUG
774 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
775 return PR_FAILURE;
779 * Can data legitimately be NULL? If not, verify..
781 #endif /* DEBUG */
783 rv = SEC_ASN1EncoderUpdate((SEC_ASN1EncoderContext *)encoder,
784 (const char *)data,
785 (unsigned long)length);
786 if( SECSuccess != rv ) {
787 nss_SetError(PORT_GetError()); /* ugly */
788 return PR_FAILURE;
791 return PR_SUCCESS;
795 * nssASN1Encoder_Finish
797 * Destructor.
799 * The error may be one of the following values:
800 * NSS_ERROR_INVALID_ASN1ENCODER
802 * Return value:
803 * PR_FAILURE upon error
804 * PR_SUCCESS upon success
807 NSS_IMPLEMENT PRStatus
808 nssASN1Encoder_Finish
810 nssASN1Encoder *encoder
813 PRStatus rv;
815 #ifdef DEBUG
816 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
817 return PR_FAILURE;
819 #endif /* DEBUG */
821 SEC_ASN1EncoderFinish((SEC_ASN1EncoderContext *)encoder);
822 rv = PR_SUCCESS; /* no error return defined for that call */
824 #ifdef DEBUG
826 PRStatus rv2 = encoder_remove_pointer(encoder);
827 if( PR_SUCCESS == rv ) {
828 rv = rv2;
831 #endif /* DEBUG */
833 return 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
849 * Return value:
850 * PR_FAILURE upon error
851 * PR_SUCCESS upon success
854 NSS_IMPLEMENT PRStatus
855 nssASN1Encoder_SetNotify
857 nssASN1Encoder *encoder,
858 nssASN1NotifyFunction *callback,
859 void *argument
862 #ifdef DEBUG
863 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
864 return PR_FAILURE;
866 #endif /* DEBUG */
868 if( (nssASN1NotifyFunction *)NULL == callback ) {
869 SEC_ASN1EncoderClearNotifyProc((SEC_ASN1EncoderContext *)encoder);
870 } else {
871 SEC_ASN1EncoderSetNotifyProc((SEC_ASN1EncoderContext *)encoder,
872 (SEC_ASN1NotifyProc)callback,
873 argument);
876 /* no error return defined for those routines */
878 return PR_SUCCESS;
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
895 * Return value:
896 * PR_FAILURE upon error
897 * PR_SUCCESS upon success
900 NSS_IMPLEMENT PRStatus
901 nssASN1Encoder_GetNotify
903 nssASN1Encoder *encoder,
904 nssASN1NotifyFunction **pCallbackOpt,
905 void **pArgumentOpt
908 #ifdef DEBUG
909 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
910 return PR_FAILURE;
912 #endif /* DEBUG */
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);
924 return PR_FAILURE;
928 * nssASN1Encoder_SetStreaming
931 * The error may be one of the following values:
932 * NSS_ERROR_INVALID_ASN1ENCODER
934 * Return value:
935 * PR_FAILURE upon error
936 * PR_SUCCESS upon success
939 NSS_IMPLEMENT PRStatus
940 nssASN1Encoder_SetStreaming
942 nssASN1Encoder *encoder,
943 PRBool streaming
946 SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext *)encoder;
948 #ifdef DEBUG
949 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
950 return PR_FAILURE;
952 #endif /* DEBUG */
954 if( streaming ) {
955 SEC_ASN1EncoderSetStreaming(cx);
956 } else {
957 SEC_ASN1EncoderClearStreaming(cx);
960 /* no error return defined for those routines */
962 return PR_SUCCESS;
966 * nssASN1Encoder_GetStreaming
969 * The error may be one of the following values:
970 * NSS_ERROR_INVALID_ASN1ENCODER
971 * NSS_ERROR_INVALID_POINTER
973 * Return value:
974 * PR_FAILURE upon error
975 * PR_SUCCESS upon success
978 NSS_EXTERN PRStatus
979 nssASN1Encoder_GetStreaming
981 nssASN1Encoder *encoder,
982 PRBool *pStreaming
985 #ifdef DEBUG
986 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
987 return PR_FAILURE;
989 #endif /* DEBUG */
991 if( (PRBool *)NULL != pStreaming ) {
992 *pStreaming = PR_FALSE;
995 /* Error because it's unimplemented */
996 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
997 return PR_FAILURE;
1001 * nssASN1Encoder_SetTakeFromBuffer
1004 * The error may be one of the following values:
1005 * NSS_ERROR_INVALID_ASN1ENCODER
1007 * Return value:
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;
1021 #ifdef DEBUG
1022 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
1023 return PR_FAILURE;
1025 #endif /* DEBUG */
1027 if( takeFromBuffer ) {
1028 SEC_ASN1EncoderSetTakeFromBuf(cx);
1029 } else {
1030 SEC_ASN1EncoderClearTakeFromBuf(cx);
1033 /* no error return defined for those routines */
1035 return PR_SUCCESS;
1039 * nssASN1Encoder_GetTakeFromBuffer
1042 * The error may be one of the following values:
1043 * NSS_ERROR_INVALID_ASN1ENCODER
1044 * NSS_ERROR_INVALID_POINTER
1046 * Return value:
1047 * PR_FAILURE upon error
1048 * PR_SUCCESS upon success
1051 NSS_IMPLEMENT PRStatus
1052 nssASN1Encoder_GetTakeFromBuffer
1054 nssASN1Encoder *encoder,
1055 PRBool *pTakeFromBuffer
1058 #ifdef DEBUG
1059 if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
1060 return PR_FAILURE;
1062 #endif /* DEBUG */
1064 if( (PRBool *)NULL != pTakeFromBuffer ) {
1065 *pTakeFromBuffer = PR_FALSE;
1068 /* Error because it's unimplemented */
1069 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
1070 return PR_FAILURE;
1074 * nssASN1_Encode
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
1082 * ...
1084 * Return value:
1085 * PR_FAILURE upon error
1086 * PR_SUCCESS upon success
1089 NSS_IMPLEMENT PRStatus
1090 nssASN1_Encode
1092 const void *source,
1093 const nssASN1Template template[],
1094 NSSASN1EncodingType encoding,
1095 nssASN1EncoderWriteFunction *sink,
1096 void *argument
1099 PRStatus rv;
1100 nssASN1Encoder *encoder;
1102 encoder = nssASN1Encoder_Create(source, template, encoding, sink, argument);
1103 if( (nssASN1Encoder *)NULL == encoder ) {
1104 return PR_FAILURE;
1107 rv = nssASN1Encoder_Update(encoder, (const void *)NULL, 0);
1108 if( PR_SUCCESS != nssASN1Encoder_Finish(encoder) ) {
1109 rv = PR_FAILURE;
1112 return rv;
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.
1122 static void
1123 nssasn1_encode_item_count
1125 void *arg,
1126 const char *buf,
1127 unsigned long len,
1128 int depth,
1129 nssASN1EncodingPart data_kind
1132 unsigned long *count;
1134 count = (unsigned long*)arg;
1135 PR_ASSERT (count != NULL);
1137 *count += len;
1141 * nssasn1_encode_item_store
1143 * This is a helper function for nssASN1_EncodeItem. It appends the
1144 * new data onto the destination item.
1147 static void
1148 nssasn1_encode_item_store
1150 void *arg,
1151 const char *buf,
1152 unsigned long len,
1153 int depth,
1154 nssASN1EncodingPart data_kind
1157 NSSItem *dest;
1159 dest = (NSSItem*)arg;
1160 PR_ASSERT (dest != NULL);
1162 memcpy((unsigned char *)dest->data + dest->size, buf, len);
1163 dest->size += 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
1180 * Return value:
1181 * NULL upon error
1182 * A valid pointer to an NSSDER upon success
1185 NSS_IMPLEMENT NSSDER *
1186 nssASN1_EncodeItem
1188 NSSArena *arenaOpt,
1189 NSSDER *rvOpt,
1190 const void *source,
1191 const nssASN1Template template[],
1192 NSSASN1EncodingType encoding
1195 NSSDER *rv;
1196 PRUint32 len = 0;
1197 PRStatus status;
1199 #ifdef DEBUG
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;
1215 #endif /* DEBUG */
1217 status = nssASN1_Encode(source, template, encoding,
1218 (nssASN1EncoderWriteFunction *)nssasn1_encode_item_count,
1219 &len);
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;
1229 } else {
1230 rv = rvOpt;
1233 rv->size = len;
1234 rv->data = nss_ZAlloc(arenaOpt, len);
1235 if( (void *)NULL == rv->data ) {
1236 if( (NSSDER *)NULL == rvOpt ) {
1237 nss_ZFreeIf(rv);
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,
1246 rv);
1247 if( PR_SUCCESS != status ) {
1248 nss_ZFreeIf(rv->data);
1249 if( (NSSDER *)NULL == rvOpt ) {
1250 nss_ZFreeIf(rv);
1252 return (NSSDER *)NULL;
1255 PR_ASSERT(rv->size == len);
1257 return rv;
1261 * nssASN1_CreatePRUint32FromBER
1265 NSS_IMPLEMENT PRStatus
1266 nssASN1_CreatePRUint32FromBER
1268 NSSBER *encoded,
1269 PRUint32 *pResult
1272 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
1273 return PR_FALSE;
1277 * nssASN1_GetDERFromPRUint32
1281 NSS_EXTERN NSSDER *
1282 nssASN1_GetDERFromPRUint32
1284 NSSArena *arenaOpt,
1285 NSSDER *rvOpt,
1286 PRUint32 value
1289 NSSDER *rv;
1290 PLArenaPool *hack = (PLArenaPool *)arenaOpt;
1291 SECItem *item;
1293 #ifdef DEBUG
1294 if( (NSSArena *)NULL != arenaOpt ) {
1295 if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
1296 return (NSSDER *)NULL;
1299 #endif /* DEBUG */
1301 if( (NSSDER *)NULL == rvOpt ) {
1302 rv = nss_ZNEW(arenaOpt, NSSDER);
1303 if( (NSSDER *)NULL == rv ) {
1304 return (NSSDER *)NULL;
1306 } else {
1307 rv = rvOpt;
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;
1327 /*himom*/
1328 NSS_IMPLEMENT PRStatus
1329 nssASN1_CreatePRInt32FromBER
1331 NSSBER *encoded,
1332 PRInt32 *pResult
1335 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
1336 return PR_FALSE;
1340 * nssASN1_GetDERFromPRInt32
1344 NSS_IMPLEMENT NSSDER *
1345 nssASN1_GetDERFromPRInt32
1347 NSSArena *arenaOpt,
1348 NSSDER *rvOpt,
1349 PRInt32 value
1352 NSSDER *rv;
1353 PLArenaPool *hack = (PLArenaPool *)arenaOpt;
1354 SECItem *item;
1356 #ifdef DEBUG
1357 if( (NSSArena *)NULL != arenaOpt ) {
1358 if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
1359 return (NSSDER *)NULL;
1362 #endif /* DEBUG */
1364 if( (NSSDER *)NULL == rvOpt ) {
1365 rv = nss_ZNEW(arenaOpt, NSSDER);
1366 if( (NSSDER *)NULL == rv ) {
1367 return (NSSDER *)NULL;
1369 } else {
1370 rv = rvOpt;
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;
1391 * Generic Templates
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
1461 NSSArena *arenaOpt,
1462 nssStringType type,
1463 NSSBER *berData
1466 NSSUTF8 *rv = NULL;
1467 PRUint8 tag;
1468 NSSArena *a;
1469 NSSItem in;
1470 NSSItem out;
1471 PRStatus st;
1472 const nssASN1Template *templ;
1474 #ifdef NSSDEBUG
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;
1497 in = *berData;
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.
1505 switch( type ) {
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))
1518 * The tags are:
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 ) {
1534 case 20:
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;
1541 break;
1542 case 19:
1543 templ = nssASN1Template_PrintableString;
1544 type = nssStringType_PrintableString;
1545 break;
1546 case 28:
1547 templ = nssASN1Template_UniversalString;
1548 type = nssStringType_UniversalString;
1549 break;
1550 case 30:
1551 templ = nssASN1Template_BMPString;
1552 type = nssStringType_BMPString;
1553 break;
1554 case 12:
1555 templ = nssASN1Template_UTF8String;
1556 type = nssStringType_UTF8String;
1557 break;
1558 default:
1559 nss_SetError(NSS_ERROR_INVALID_POINTER); /* "pointer"? */
1560 (void)NSSArena_Destroy(a);
1561 return (NSSUTF8 *)NULL;
1564 break;
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;
1572 break;
1574 case nssStringType_PrintableString:
1575 templ = nssASN1Template_PrintableString;
1576 break;
1578 case nssStringType_UniversalString:
1579 templ = nssASN1Template_UniversalString;
1580 break;
1582 case nssStringType_BMPString:
1583 templ = nssASN1Template_BMPString;
1584 break;
1586 case nssStringType_UTF8String:
1587 templ = nssASN1Template_UTF8String;
1588 break;
1590 case nssStringType_PHGString:
1591 templ = nssASN1Template_IA5String;
1592 break;
1594 default:
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);
1607 return rv;
1610 NSS_EXTERN NSSDER *
1611 nssUTF8_GetDEREncoding
1613 NSSArena *arenaOpt,
1614 nssStringType type,
1615 const NSSUTF8 *string
1618 NSSDER *rv = (NSSDER *)NULL;
1619 NSSItem str;
1620 NSSDER *der;
1621 const nssASN1Template *templ;
1622 NSSArena *a;
1624 #ifdef NSSDEBUG
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;
1648 switch( type ) {
1649 case nssStringType_DirectoryString:
1651 NSSDER *utf;
1652 PRUint8 *c;
1654 utf = nssASN1_EncodeItem(a, (NSSDER *)NULL, &str,
1655 nssASN1Template_UTF8String,
1656 NSSASN1DER);
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);
1681 return rv;
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;
1689 break;
1690 case nssStringType_PrintableString:
1691 templ = nssASN1Template_PrintableString;
1692 break;
1694 case nssStringType_UniversalString:
1695 templ = nssASN1Template_UniversalString;
1696 break;
1698 case nssStringType_BMPString:
1699 templ = nssASN1Template_BMPString;
1700 break;
1702 case nssStringType_UTF8String:
1703 templ = nssASN1Template_UTF8String;
1704 break;
1706 case nssStringType_PHGString:
1707 templ = nssASN1Template_IA5String;
1708 break;
1710 default:
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);
1729 return rv;