Back to index

lightning-sunbird  0.9+nobinonly
asn1.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: asn1.c,v $ $Revision: 1.4 $ $Date: 2005/01/20 02:25:44 $";
00039 #endif /* DEBUG */
00040 
00041 /*
00042  * asn1.c
00043  *
00044  * At this point in time, this file contains the NSS wrappers for
00045  * the old "SEC" ASN.1 encoder/decoder stuff.
00046  */
00047 
00048 #ifndef ASN1M_H
00049 #include "asn1m.h"
00050 #endif /* ASN1M_H */
00051 
00052 #include "plarena.h"
00053 #include "secasn1.h"
00054 
00055 /*
00056  * The pointer-tracking stuff
00057  */
00058 
00059 #ifdef DEBUG
00060 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
00061 
00062 static nssPointerTracker decoder_pointer_tracker;
00063 
00064 static PRStatus
00065 decoder_add_pointer
00066 (
00067   const nssASN1Decoder *decoder
00068 )
00069 {
00070   PRStatus rv;
00071 
00072   rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
00073   if( PR_SUCCESS != rv ) {
00074     return rv;
00075   }
00076 
00077   rv = nssPointerTracker_add(&decoder_pointer_tracker, decoder);
00078   if( PR_SUCCESS != rv ) {
00079     NSSError e = NSS_GetError();
00080     if( NSS_ERROR_NO_MEMORY != e ) {
00081       nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00082     }
00083 
00084     return rv;
00085   }
00086 
00087   return PR_SUCCESS;
00088 }
00089 
00090 static PRStatus
00091 decoder_remove_pointer
00092 (
00093   const nssASN1Decoder *decoder
00094 )
00095 {
00096   PRStatus rv;
00097 
00098   rv = nssPointerTracker_remove(&decoder_pointer_tracker, decoder);
00099   if( PR_SUCCESS != rv ) {
00100     nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00101   }
00102 
00103   return rv;
00104 }
00105 
00106 /*
00107  * nssASN1Decoder_verify
00108  *
00109  * This routine is only available in debug builds.
00110  *
00111  * If the specified pointer is a valid pointer to an nssASN1Decoder
00112  * object, this routine will return PR_SUCCESS.  Otherwise, it will 
00113  * put an error on the error stack and return PR_FAILURE.
00114  *
00115  * The error may be one of the following values:
00116  *  NSS_ERROR_INVALID_ASN1DECODER
00117  *
00118  * Return value:
00119  *  PR_FAILURE upon error
00120  *  PR_SUCCESS upon success
00121  */
00122 
00123 NSS_IMPLEMENT PRStatus
00124 nssASN1Decoder_verify
00125 (
00126   nssASN1Decoder *decoder
00127 )
00128 {
00129   PRStatus rv;
00130 
00131   rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
00132   if( PR_SUCCESS != rv ) {
00133     return PR_FAILURE;
00134   }
00135 
00136   rv = nssPointerTracker_verify(&decoder_pointer_tracker, decoder);
00137   if( PR_SUCCESS != rv ) {
00138     nss_SetError(NSS_ERROR_INVALID_ASN1DECODER);
00139     return PR_FAILURE;
00140   }
00141 
00142   return PR_SUCCESS;
00143 }
00144 
00145 static nssPointerTracker encoder_pointer_tracker;
00146 
00147 static PRStatus
00148 encoder_add_pointer
00149 (
00150   const nssASN1Encoder *encoder
00151 )
00152 {
00153   PRStatus rv;
00154 
00155   rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
00156   if( PR_SUCCESS != rv ) {
00157     return rv;
00158   }
00159 
00160   rv = nssPointerTracker_add(&encoder_pointer_tracker, encoder);
00161   if( PR_SUCCESS != rv ) {
00162     NSSError e = NSS_GetError();
00163     if( NSS_ERROR_NO_MEMORY != e ) {
00164       nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00165     }
00166 
00167     return rv;
00168   }
00169 
00170   return PR_SUCCESS;
00171 }
00172 
00173 static PRStatus
00174 encoder_remove_pointer
00175 (
00176   const nssASN1Encoder *encoder
00177 )
00178 {
00179   PRStatus rv;
00180 
00181   rv = nssPointerTracker_remove(&encoder_pointer_tracker, encoder);
00182   if( PR_SUCCESS != rv ) {
00183     nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00184   }
00185 
00186   return rv;
00187 }
00188 
00189 /*
00190  * nssASN1Encoder_verify
00191  *
00192  * This routine is only available in debug builds.
00193  *
00194  * If the specified pointer is a valid pointer to an nssASN1Encoder
00195  * object, this routine will return PR_SUCCESS.  Otherwise, it will 
00196  * put an error on the error stack and return PR_FAILURE.
00197  *
00198  * The error may be one of the following values:
00199  *  NSS_ERROR_INVALID_ASN1ENCODER
00200  *
00201  * Return value:
00202  *  PR_FAILURE upon error
00203  *  PR_SUCCESS upon success
00204  */
00205 
00206 NSS_IMPLEMENT PRStatus
00207 nssASN1Encoder_verify
00208 (
00209   nssASN1Encoder *encoder
00210 )
00211 {
00212   PRStatus rv;
00213 
00214   rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
00215   if( PR_SUCCESS != rv ) {
00216     return PR_FAILURE;
00217   }
00218 
00219   rv = nssPointerTracker_verify(&encoder_pointer_tracker, encoder);
00220   if( PR_SUCCESS != rv ) {
00221     nss_SetError(NSS_ERROR_INVALID_ASN1ENCODER);
00222     return PR_FAILURE;
00223   }
00224 
00225   return PR_SUCCESS;
00226 }
00227 #endif /* DEBUG */
00228 
00229 /*
00230  * nssASN1Decoder_Create
00231  *
00232  * This routine creates an ASN.1 Decoder, which will use the specified
00233  * template to decode a datastream into the specified destination
00234  * structure.  If the optional arena argument is non-NULL, blah blah 
00235  * blah.  XXX fgmr Should we include an nssASN1EncodingType argument, 
00236  * as a hint?  Or is each encoding distinctive?  This routine may 
00237  * return NULL upon error, in which case an error will have been 
00238  * placed upon the error stack.
00239  *
00240  * The error may be one of the following values:
00241  *  NSS_ERROR_NO_MEMORY
00242  *  NSS_ERROR_INVALID_ARENA
00243  *  NSS_ERROR_INVALID_POINTER
00244  *  ...
00245  *
00246  * Return value:
00247  *  NULL upon error
00248  *  A pointer to an ASN.1 Decoder upon success.
00249  */
00250 
00251 NSS_IMPLEMENT nssASN1Decoder *
00252 nssASN1Decoder_Create
00253 (
00254   NSSArena *arenaOpt,
00255   void *destination,
00256   const nssASN1Template template[]
00257 )
00258 {
00259   SEC_ASN1DecoderContext *rv;
00260   PLArenaPool *hack = (PLArenaPool *)arenaOpt;
00261 
00262 #ifdef DEBUG
00263   if( (NSSArena *)NULL != arenaOpt ) {
00264     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
00265       return (nssASN1Decoder *)NULL;
00266     }
00267   }
00268 
00269   /* 
00270    * May destination be NULL?  I'd think so, since one might
00271    * have only a filter proc.  But if not, check the pointer here.
00272    */
00273 
00274   if( (nssASN1Template *)NULL == template ) {
00275     nss_SetError(NSS_ERROR_INVALID_POINTER);
00276     return (nssASN1Decoder *)NULL;
00277   }
00278 #endif /* DEBUG */
00279 
00280   rv = SEC_ASN1DecoderStart(hack, destination, template);
00281   if( (SEC_ASN1DecoderContext *)NULL == rv ) {
00282     nss_SetError(PORT_GetError()); /* also evil */
00283     return (nssASN1Decoder *)NULL;
00284   }
00285 
00286 #ifdef DEBUG
00287   if( PR_SUCCESS != decoder_add_pointer(rv) ) {
00288     (void)SEC_ASN1DecoderFinish(rv);
00289     return (nssASN1Decoder *)NULL;
00290   }
00291 #endif /* DEBUG */
00292 
00293   return (nssASN1Decoder *)rv;
00294 }
00295 
00296 /*
00297  * nssASN1Decoder_Update
00298  *
00299  * This routine feeds data to the decoder.  In the event of an error, 
00300  * it will place an error on the error stack and return PR_FAILURE.
00301  *
00302  * The error may be one of the following values:
00303  *  NSS_ERROR_NO_MEMORY
00304  *  NSS_ERROR_INVALID_POINTER
00305  *  NSS_ERROR_INVALID_ASN1DECODER
00306  *  NSS_ERROR_INVALID_BER
00307  *  ...
00308  *
00309  * Return value:
00310  *  PR_FAILURE upon error
00311  *  PR_SUCCESS upon success.
00312  */
00313 
00314 NSS_IMPLEMENT PRStatus
00315 nssASN1Decoder_Update
00316 (
00317   nssASN1Decoder *decoder,
00318   const void *data,
00319   PRUint32 amount
00320 )
00321 {
00322   SECStatus rv;
00323 
00324 #ifdef DEBUG
00325   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
00326     return PR_FAILURE;
00327   }
00328 
00329   if( (void *)NULL == data ) {
00330     nss_SetError(NSS_ERROR_INVALID_POINTER);
00331     return PR_FAILURE;
00332   }
00333 #endif /* DEBUG */
00334 
00335   rv = SEC_ASN1DecoderUpdate((SEC_ASN1DecoderContext *)decoder, 
00336                              (const char *)data,
00337                              (unsigned long)amount);
00338   if( SECSuccess != rv ) {
00339     nss_SetError(PORT_GetError()); /* ugly */
00340     return PR_FAILURE;
00341   }
00342 
00343   return PR_SUCCESS;
00344 }
00345 
00346 /*
00347  * nssASN1Decoder_Finish
00348  *
00349  * This routine finishes the decoding and destroys the decoder.
00350  * In the event of an error, it will place an error on the error
00351  * stack and return PR_FAILURE.
00352  *
00353  * The error may be one of the following values:
00354  *  NSS_ERROR_INVALID_ASN1DECODER
00355  *
00356  * Return value:
00357  *  PR_FAILURE upon error
00358  *  PR_SUCCESS upon success
00359  */
00360 
00361 NSS_IMPLEMENT PRStatus
00362 nssASN1Decoder_Finish
00363 (
00364   nssASN1Decoder *decoder
00365 )
00366 {
00367   PRStatus rv = PR_SUCCESS;
00368   SECStatus srv;
00369 
00370 #ifdef DEBUG
00371   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
00372     return PR_FAILURE;
00373   }
00374 #endif /* DEBUG */
00375 
00376   srv = SEC_ASN1DecoderFinish((SEC_ASN1DecoderContext *)decoder);
00377 
00378   if( SECSuccess != srv ) {
00379     nss_SetError(PORT_GetError()); /* ugly */
00380     rv = PR_FAILURE;
00381   }
00382 
00383 #ifdef DEBUG
00384   {
00385     PRStatus rv2 = decoder_remove_pointer(decoder);
00386     if( PR_SUCCESS == rv ) {
00387       rv = rv2;
00388     }
00389   }
00390 #endif /* DEBUG */
00391 
00392   return rv;
00393 }
00394 
00395 /*
00396  * nssASN1Decoder_SetFilter
00397  *
00398  * This routine registers a callback filter routine with the decoder,
00399  * which will be called blah blah blah.  The specified argument will
00400  * be passed as-is to the filter routine.  The routine pointer may
00401  * be NULL, in which case no filter callback will be called.  If the
00402  * noStore boolean is PR_TRUE, then decoded fields will not be stored
00403  * in the destination structure specified when the decoder was 
00404  * created.  This routine returns a PRStatus value; in the event of
00405  * an error, it will place an error on the error stack and return
00406  * PR_FAILURE.
00407  *
00408  * The error may be one of the following values:
00409  *  NSS_ERROR_INVALID_ASN1DECODER
00410  *
00411  * Return value:
00412  *  PR_FAILURE upon error
00413  *  PR_SUCCESS upon success
00414  */
00415 
00416 NSS_IMPLEMENT PRStatus
00417 nssASN1Decoder_SetFilter
00418 (
00419   nssASN1Decoder *decoder,
00420   nssASN1DecoderFilterFunction *callback,
00421   void *argument,
00422   PRBool noStore
00423 )
00424 {
00425 #ifdef DEBUG
00426   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
00427     return PR_FAILURE;
00428   }
00429 #endif /* DEBUG */
00430 
00431   if( (nssASN1DecoderFilterFunction *)NULL == callback ) {
00432      SEC_ASN1DecoderClearFilterProc((SEC_ASN1DecoderContext *)decoder);
00433   } else {
00434      SEC_ASN1DecoderSetFilterProc((SEC_ASN1DecoderContext *)decoder,
00435                                   (SEC_ASN1WriteProc)callback,
00436                                   argument, noStore);
00437   }
00438 
00439   /* No error returns defined for those routines */
00440 
00441   return PR_SUCCESS;
00442 }
00443 
00444 /*
00445  * nssASN1Decoder_GetFilter
00446  *
00447  * If the optional pCallbackOpt argument to this routine is non-null,
00448  * then the pointer to any callback function established for this
00449  * decoder with nssASN1Decoder_SetFilter will be stored at the 
00450  * location indicated by it.  If the optional pArgumentOpt
00451  * pointer is non-null, the filter's closure argument will be stored
00452  * there.  If the optional pNoStoreOpt pointer is non-null, the
00453  * noStore value specified when setting the filter will be stored
00454  * there.  This routine returns a PRStatus value; in the event of
00455  * an error it will place an error on the error stack and return
00456  * PR_FAILURE.
00457  *
00458  * The error may be one of the following values:
00459  *  NSS_ERROR_INVALID_ASN1DECODER
00460  *
00461  * Return value:
00462  *  PR_FAILURE upon error
00463  *  PR_SUCCESS upon success
00464  */
00465 
00466 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
00467 
00468 NSS_IMPLEMENT PRStatus
00469 nssASN1Decoder_GetFilter
00470 (
00471   nssASN1Decoder *decoder,
00472   nssASN1DecoderFilterFunction **pCallbackOpt,
00473   void **pArgumentOpt,
00474   PRBool *pNoStoreOpt
00475 )
00476 {
00477 #ifdef DEBUG
00478   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
00479     return PR_FAILURE;
00480   }
00481 #endif /* DEBUG */
00482 
00483   if( (nssASN1DecoderFilterFunction **)NULL != pCallbackOpt ) {
00484     *pCallbackOpt = (nssASN1DecoderFilterFunction *)NULL;
00485   }
00486 
00487   if( (void **)NULL != pArgumentOpt ) {
00488     *pArgumentOpt = (void *)NULL;
00489   }
00490 
00491   if( (PRBool *)NULL != pNoStoreOpt ) {
00492     *pNoStoreOpt = PR_FALSE;
00493   }
00494 
00495   /* Error because it's unimplemented */
00496   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00497   return PR_FAILURE;
00498 }
00499 
00500 /*
00501  * nssASN1Decoder_SetNotify
00502  *
00503  * This routine registers a callback notify routine with the decoder,
00504  * which will be called whenever.. The specified argument will be
00505  * passed as-is to the notify routine.  The routine pointer may be
00506  * NULL, in which case no notify routine will be called.  This routine
00507  * returns a PRStatus value; in the event of an error it will place
00508  * an error on the error stack and return PR_FAILURE.
00509  *
00510  * The error may be one of the following values:
00511  *  NSS_ERROR_INVALID_ASN1DECODER
00512  *
00513  * Return value:
00514  *  PR_FAILURE upon error
00515  *  PR_SUCCESS upon success
00516  */
00517 
00518 NSS_IMPLEMENT PRStatus
00519 nssASN1Decoder_SetNotify
00520 (
00521   nssASN1Decoder *decoder,
00522   nssASN1NotifyFunction *callback,
00523   void *argument
00524 )
00525 {
00526 #ifdef DEBUG
00527   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
00528     return PR_FAILURE;
00529   }
00530 #endif /* DEBUG */
00531 
00532   if( (nssASN1NotifyFunction *)NULL == callback ) {
00533     SEC_ASN1DecoderClearNotifyProc((SEC_ASN1DecoderContext *)decoder);
00534   } else {
00535     SEC_ASN1DecoderSetNotifyProc((SEC_ASN1DecoderContext *)decoder,
00536                                  (SEC_ASN1NotifyProc)callback,
00537                                  argument);
00538   }
00539 
00540   /* No error returns defined for those routines */
00541 
00542   return PR_SUCCESS;
00543 }
00544 
00545 /*
00546  * nssASN1Decoder_GetNotify
00547  *
00548  * If the optional pCallbackOpt argument to this routine is non-null,
00549  * then the pointer to any callback function established for this
00550  * decoder with nssASN1Decoder_SetNotify will be stored at the 
00551  * location indicated by it.  If the optional pArgumentOpt pointer is
00552  * non-null, the filter's closure argument will be stored there.
00553  * This routine returns a PRStatus value; in the event of an error it
00554  * will place an error on the error stack and return PR_FAILURE.
00555  *
00556  * The error may be one of the following values:
00557  *  NSS_ERROR_INVALID_ASN1DECODER
00558  *
00559  * Return value:
00560  *  PR_FAILURE upon error
00561  *  PR_SUCCESS upon success
00562  */
00563 
00564 NSS_IMPLEMENT PRStatus
00565 nssASN1Decoder_GetNotify
00566 (
00567   nssASN1Decoder *decoder,
00568   nssASN1NotifyFunction **pCallbackOpt,
00569   void **pArgumentOpt
00570 )
00571 {
00572 #ifdef DEBUG
00573   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
00574     return PR_FAILURE;
00575   }
00576 #endif /* DEBUG */
00577 
00578   if( (nssASN1NotifyFunction **)NULL != pCallbackOpt ) {
00579     *pCallbackOpt = (nssASN1NotifyFunction *)NULL;
00580   }
00581 
00582   if( (void **)NULL != pArgumentOpt ) {
00583     *pArgumentOpt = (void *)NULL;
00584   }
00585 
00586   /* Error because it's unimplemented */
00587   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00588   return PR_FAILURE;
00589 }
00590 
00591 /*
00592  * nssASN1_Decode
00593  *
00594  * This routine will decode the specified data into the specified
00595  * destination structure, as specified by the specified template.
00596  * This routine returns a PRStatus value; in the event of an error
00597  * it will place an error on the error stack and return PR_FAILURE.
00598  *
00599  * The error may be one of the following values:
00600  *  NSS_ERROR_NO_MEMORY
00601  *  NSS_ERROR_INVALID_ARENA
00602  *  NSS_ERROR_INVALID_POINTER
00603  *  NSS_ERROR_INVALID_BER
00604  *
00605  * Return value:
00606  *  PR_FAILURE upon error
00607  *  PR_SUCCESS upon success
00608  */
00609 
00610 NSS_IMPLEMENT PRStatus
00611 nssASN1_Decode
00612 (
00613   NSSArena *arenaOpt,
00614   void *destination,
00615   const nssASN1Template template[],
00616   const void *berData,
00617   PRUint32 amount
00618 )
00619 {
00620   PRStatus rv;
00621   nssASN1Decoder *decoder;
00622 
00623   /* This call will do our pointer-checking for us! */
00624   decoder = nssASN1Decoder_Create(arenaOpt, destination, template);
00625   if( (nssASN1Decoder *)NULL == decoder ) {
00626     return PR_FAILURE;
00627   }
00628 
00629   rv = nssASN1Decoder_Update(decoder, berData, amount);
00630   if( PR_SUCCESS != nssASN1Decoder_Finish(decoder) ) {
00631     rv = PR_FAILURE;
00632   }
00633 
00634   return rv;
00635 }
00636 
00637 /*
00638  * nssASN1_DecodeBER
00639  *
00640  * This routine will decode the data in the specified NSSBER
00641  * into the destination structure, as specified by the template.
00642  * This routine returns a PRStatus value; in the event of an error
00643  * it will place an error on the error stack and return PR_FAILURE.
00644  *
00645  * The error may be one of the following values:
00646  *  NSS_ERROR_NO_MEMORY
00647  *  NSS_ERROR_INVALID_ARENA
00648  *  NSS_ERROR_INVALID_POINTER
00649  *  NSS_ERROR_INVALID_NSSBER
00650  *  NSS_ERROR_INVALID_BER
00651  *
00652  * Return value:
00653  *  PR_FAILURE upon error
00654  *  PR_SUCCESS upon success
00655  */
00656 
00657 NSS_IMPLEMENT PRStatus
00658 nssASN1_DecodeBER
00659 (
00660   NSSArena *arenaOpt,
00661   void *destination,
00662   const nssASN1Template template[],
00663   const NSSBER *data
00664 )
00665 {
00666   return nssASN1_Decode(arenaOpt, destination, template, 
00667                         data->data, data->size);
00668 }
00669 
00670 /*
00671  * nssASN1Encoder_Create
00672  *
00673  * This routine creates an ASN.1 Encoder, blah blah blah.  This 
00674  * may return NULL upon error, in which case an error will have been
00675  * placed on the error stack.
00676  *
00677  * The error may be one of the following values:
00678  *  NSS_ERROR_NO_MEMORY
00679  *  NSS_ERROR_INVALID_ARENA
00680  *  NSS_ERROR_INVALID_POINTER
00681  *  ...
00682  *
00683  * Return value:
00684  *  NULL upon error
00685  *  A pointer to an ASN.1 Encoder upon success
00686  */
00687 
00688 NSS_IMPLEMENT nssASN1Encoder *
00689 nssASN1Encoder_Create
00690 (
00691   const void *source,
00692   const nssASN1Template template[],
00693   NSSASN1EncodingType encoding,
00694   nssASN1EncoderWriteFunction *sink,
00695   void *argument
00696 )
00697 {
00698   SEC_ASN1EncoderContext *rv;
00699 
00700 #ifdef DEBUG
00701   if( (void *)NULL == source ) {
00702     nss_SetError(NSS_ERROR_INVALID_POINTER);
00703     return (nssASN1Encoder *)NULL;
00704   }
00705 
00706   if( (nssASN1Template *)NULL == template ) {
00707     nss_SetError(NSS_ERROR_INVALID_POINTER);
00708     return (nssASN1Encoder *)NULL;
00709   }
00710 
00711   if( (nssASN1EncoderWriteFunction *)NULL == sink ) {
00712     nss_SetError(NSS_ERROR_INVALID_POINTER);
00713     return (nssASN1Encoder *)NULL;
00714   }
00715 #endif /* DEBUG */
00716 
00717   switch( encoding ) {
00718   case NSSASN1BER:
00719   case NSSASN1DER:
00720     break;
00721   case NSSASN1CER:
00722   case NSSASN1LWER:
00723   case NSSASN1PER:
00724   case NSSASN1UnknownEncoding:
00725   default:
00726     nss_SetError(NSS_ERROR_ENCODING_NOT_SUPPORTED);
00727     return (nssASN1Encoder *)NULL;
00728   }
00729 
00730   rv = SEC_ASN1EncoderStart((void *)source, template, 
00731                             (SEC_ASN1WriteProc)sink, argument);
00732   if( (SEC_ASN1EncoderContext *)NULL == rv ) {
00733     nss_SetError(PORT_GetError()); /* ugly */
00734     return (nssASN1Encoder *)NULL;
00735   }
00736 
00737   if( NSSASN1DER == encoding ) {
00738     sec_ASN1EncoderSetDER(rv);
00739   }
00740 
00741 #ifdef DEBUG
00742   if( PR_SUCCESS != encoder_add_pointer(rv) ) {
00743     (void)SEC_ASN1EncoderFinish(rv);
00744     return (nssASN1Encoder *)NULL;
00745   }
00746 #endif /* DEBUG */
00747 
00748   return (nssASN1Encoder *)rv;
00749 }
00750 
00751 /*
00752  * nssASN1Encoder_Update
00753  *
00754  * The error may be one of the following values:
00755  *  NSS_ERROR_INVALID_ASN1ENCODER
00756  *  NSS_ERROR_INVALID_POINTER
00757  *
00758  * Return value:
00759  *  PR_FAILURE upon error
00760  *  PR_SUCCESS upon success
00761  */
00762 
00763 NSS_IMPLEMENT PRStatus
00764 nssASN1Encoder_Update
00765 (
00766   nssASN1Encoder *encoder,
00767   const void *data,
00768   PRUint32 length
00769 )
00770 {
00771   SECStatus rv;
00772 
00773 #ifdef DEBUG
00774   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
00775     return PR_FAILURE;
00776   }
00777 
00778   /*
00779    * Can data legitimately be NULL?  If not, verify..
00780    */
00781 #endif /* DEBUG */
00782 
00783   rv = SEC_ASN1EncoderUpdate((SEC_ASN1EncoderContext *)encoder,
00784                              (const char *)data, 
00785                              (unsigned long)length);
00786   if( SECSuccess != rv ) {
00787     nss_SetError(PORT_GetError()); /* ugly */
00788     return PR_FAILURE;
00789   }
00790 
00791   return PR_SUCCESS;
00792 }
00793 
00794 /*
00795  * nssASN1Encoder_Finish
00796  *
00797  * Destructor.
00798  *
00799  * The error may be one of the following values:
00800  *  NSS_ERROR_INVALID_ASN1ENCODER
00801  *
00802  * Return value:
00803  *  PR_FAILURE upon error
00804  *  PR_SUCCESS upon success
00805  */
00806 
00807 NSS_IMPLEMENT PRStatus
00808 nssASN1Encoder_Finish
00809 (
00810   nssASN1Encoder *encoder
00811 )
00812 {
00813   PRStatus rv;
00814 
00815 #ifdef DEBUG
00816   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
00817     return PR_FAILURE;
00818   }
00819 #endif /* DEBUG */
00820 
00821   SEC_ASN1EncoderFinish((SEC_ASN1EncoderContext *)encoder);
00822   rv = PR_SUCCESS; /* no error return defined for that call */
00823 
00824 #ifdef DEBUG
00825   {
00826     PRStatus rv2 = encoder_remove_pointer(encoder);
00827     if( PR_SUCCESS == rv ) {
00828       rv = rv2;
00829     }
00830   }
00831 #endif /* DEBUG */
00832 
00833   return rv;
00834 }
00835 
00836 /*
00837  * nssASN1Encoder_SetNotify
00838  *
00839  * This routine registers a callback notify routine with the encoder,
00840  * which will be called whenever.. The specified argument will be
00841  * passed as-is to the notify routine.  The routine pointer may be
00842  * NULL, in which case no notify routine will be called.  This routine
00843  * returns a PRStatus value; in the event of an error it will place
00844  * an error on the error stack and return PR_FAILURE.
00845  *
00846  * The error may be one of the following values:
00847  *  NSS_ERROR_INVALID_ASN1DECODER
00848  *
00849  * Return value:
00850  *  PR_FAILURE upon error
00851  *  PR_SUCCESS upon success
00852  */
00853 
00854 NSS_IMPLEMENT PRStatus
00855 nssASN1Encoder_SetNotify
00856 (
00857   nssASN1Encoder *encoder,
00858   nssASN1NotifyFunction *callback,
00859   void *argument
00860 )
00861 {
00862 #ifdef DEBUG
00863   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
00864     return PR_FAILURE;
00865   }
00866 #endif /* DEBUG */
00867 
00868   if( (nssASN1NotifyFunction *)NULL == callback ) {
00869     SEC_ASN1EncoderClearNotifyProc((SEC_ASN1EncoderContext *)encoder);
00870   } else {
00871     SEC_ASN1EncoderSetNotifyProc((SEC_ASN1EncoderContext *)encoder,
00872                                  (SEC_ASN1NotifyProc)callback,
00873                                  argument);
00874   }
00875 
00876   /* no error return defined for those routines */
00877 
00878   return PR_SUCCESS;
00879 }
00880 
00881 /*
00882  * nssASN1Encoder_GetNotify
00883  *
00884  * If the optional pCallbackOpt argument to this routine is non-null,
00885  * then the pointer to any callback function established for this
00886  * decoder with nssASN1Encoder_SetNotify will be stored at the 
00887  * location indicated by it.  If the optional pArgumentOpt pointer is
00888  * non-null, the filter's closure argument will be stored there.
00889  * This routine returns a PRStatus value; in the event of an error it
00890  * will place an error on the error stack and return PR_FAILURE.
00891  *
00892  * The error may be one of the following values:
00893  *  NSS_ERROR_INVALID_ASN1ENCODER
00894  *
00895  * Return value:
00896  *  PR_FAILURE upon error
00897  *  PR_SUCCESS upon success
00898  */
00899 
00900 NSS_IMPLEMENT PRStatus
00901 nssASN1Encoder_GetNotify
00902 (
00903   nssASN1Encoder *encoder,
00904   nssASN1NotifyFunction **pCallbackOpt,
00905   void **pArgumentOpt
00906 )
00907 {
00908 #ifdef DEBUG
00909   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
00910     return PR_FAILURE;
00911   }
00912 #endif /* DEBUG */
00913 
00914   if( (nssASN1NotifyFunction **)NULL != pCallbackOpt ) {
00915     *pCallbackOpt = (nssASN1NotifyFunction *)NULL;
00916   }
00917 
00918   if( (void **)NULL != pArgumentOpt ) {
00919     *pArgumentOpt = (void *)NULL;
00920   }
00921 
00922   /* Error because it's unimplemented */
00923   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00924   return PR_FAILURE;
00925 }
00926 
00927 /*
00928  * nssASN1Encoder_SetStreaming
00929  *
00930  * 
00931  * The error may be one of the following values:
00932  *  NSS_ERROR_INVALID_ASN1ENCODER
00933  *
00934  * Return value:
00935  *  PR_FAILURE upon error
00936  *  PR_SUCCESS upon success
00937  */
00938 
00939 NSS_IMPLEMENT PRStatus
00940 nssASN1Encoder_SetStreaming
00941 (
00942   nssASN1Encoder *encoder,
00943   PRBool streaming
00944 )
00945 {
00946   SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext *)encoder;
00947 
00948 #ifdef DEBUG
00949   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
00950     return PR_FAILURE;
00951   }
00952 #endif /* DEBUG */
00953 
00954   if( streaming ) {
00955     SEC_ASN1EncoderSetStreaming(cx);
00956   } else {
00957     SEC_ASN1EncoderClearStreaming(cx);
00958   }
00959 
00960   /* no error return defined for those routines */
00961 
00962   return PR_SUCCESS;
00963 }
00964 
00965 /*
00966  * nssASN1Encoder_GetStreaming
00967  *
00968  *
00969  * The error may be one of the following values:
00970  *  NSS_ERROR_INVALID_ASN1ENCODER
00971  *  NSS_ERROR_INVALID_POINTER
00972  *
00973  * Return value:
00974  *  PR_FAILURE upon error
00975  *  PR_SUCCESS upon success
00976  */
00977 
00978 NSS_EXTERN PRStatus
00979 nssASN1Encoder_GetStreaming
00980 (
00981   nssASN1Encoder *encoder,
00982   PRBool *pStreaming
00983 )
00984 {
00985 #ifdef DEBUG
00986   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
00987     return PR_FAILURE;
00988   }
00989 #endif /* DEBUG */
00990 
00991   if( (PRBool *)NULL != pStreaming ) {
00992     *pStreaming = PR_FALSE;
00993   }
00994 
00995   /* Error because it's unimplemented */
00996   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00997   return PR_FAILURE;
00998 }
00999 
01000 /*
01001  * nssASN1Encoder_SetTakeFromBuffer
01002  *
01003  *
01004  * The error may be one of the following values:
01005  *  NSS_ERROR_INVALID_ASN1ENCODER
01006  *
01007  * Return value:
01008  *  PR_FAILURE upon error
01009  *  PR_SUCCESS upon success
01010  */
01011 
01012 NSS_IMPLEMENT PRStatus
01013 nssASN1Encoder_SetTakeFromBuffer
01014 (
01015   nssASN1Encoder *encoder,
01016   PRBool takeFromBuffer
01017 )
01018 {
01019   SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext *)encoder;
01020 
01021 #ifdef DEBUG
01022   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
01023     return PR_FAILURE;
01024   }
01025 #endif /* DEBUG */
01026 
01027   if( takeFromBuffer ) {
01028     SEC_ASN1EncoderSetTakeFromBuf(cx);
01029   } else {
01030     SEC_ASN1EncoderClearTakeFromBuf(cx);
01031   }
01032 
01033   /* no error return defined for those routines */
01034 
01035   return PR_SUCCESS;
01036 }
01037 
01038 /*
01039  * nssASN1Encoder_GetTakeFromBuffer
01040  *
01041  *
01042  * The error may be one of the following values:
01043  *  NSS_ERROR_INVALID_ASN1ENCODER
01044  *  NSS_ERROR_INVALID_POINTER
01045  *
01046  * Return value:
01047  *  PR_FAILURE upon error
01048  *  PR_SUCCESS upon success
01049  */
01050 
01051 NSS_IMPLEMENT PRStatus
01052 nssASN1Encoder_GetTakeFromBuffer
01053 (
01054   nssASN1Encoder *encoder,
01055   PRBool *pTakeFromBuffer
01056 )
01057 {
01058 #ifdef DEBUG
01059   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
01060     return PR_FAILURE;
01061   }
01062 #endif /* DEBUG */
01063 
01064   if( (PRBool *)NULL != pTakeFromBuffer ) {
01065     *pTakeFromBuffer = PR_FALSE;
01066   }
01067 
01068   /* Error because it's unimplemented */
01069   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
01070   return PR_FAILURE;
01071 }
01072 
01073 /*
01074  * nssASN1_Encode
01075  *
01076  * 
01077  * The error may be one of the following values:
01078  *  NSS_ERROR_NO_MEMORY
01079  *  NSS_ERROR_INVALID_ARENA
01080  *  NSS_ERROR_INVALID_POINTER
01081  *  NSS_ERROR_ENCODING_NOT_SUPPORTED
01082  *  ...
01083  *
01084  * Return value:
01085  *  PR_FAILURE upon error
01086  *  PR_SUCCESS upon success
01087  */
01088 
01089 NSS_IMPLEMENT PRStatus
01090 nssASN1_Encode
01091 (
01092   const void *source,
01093   const nssASN1Template template[],
01094   NSSASN1EncodingType encoding,
01095   nssASN1EncoderWriteFunction *sink,
01096   void *argument
01097 )
01098 {
01099   PRStatus rv;
01100   nssASN1Encoder *encoder;
01101 
01102   encoder = nssASN1Encoder_Create(source, template, encoding, sink, argument);
01103   if( (nssASN1Encoder *)NULL == encoder ) {
01104     return PR_FAILURE;
01105   }
01106 
01107   rv = nssASN1Encoder_Update(encoder, (const void *)NULL, 0);
01108   if( PR_SUCCESS != nssASN1Encoder_Finish(encoder) ) {
01109     rv = PR_FAILURE;
01110   }
01111 
01112   return rv;
01113 }
01114 
01115 /*
01116  * nssasn1_encode_item_count
01117  *
01118  * This is a helper function for nssASN1_EncodeItem.  It just counts
01119  * up the space required for an encoding.
01120  */
01121 
01122 static void
01123 nssasn1_encode_item_count
01124 (
01125   void *arg,
01126   const char *buf,
01127   unsigned long len,
01128   int depth,
01129   nssASN1EncodingPart data_kind
01130 )
01131 {
01132   unsigned long *count;
01133 
01134   count = (unsigned long*)arg;
01135   PR_ASSERT (count != NULL);
01136 
01137   *count += len;
01138 }
01139 
01140 /*
01141  * nssasn1_encode_item_store
01142  *
01143  * This is a helper function for nssASN1_EncodeItem.  It appends the
01144  * new data onto the destination item.
01145  */
01146 
01147 static void
01148 nssasn1_encode_item_store
01149 (
01150   void *arg,
01151   const char *buf,
01152   unsigned long len,
01153   int depth,
01154   nssASN1EncodingPart data_kind
01155 )
01156 {
01157   NSSItem *dest;
01158 
01159   dest = (NSSItem*)arg;
01160   PR_ASSERT (dest != NULL);
01161 
01162   memcpy((unsigned char *)dest->data + dest->size, buf, len);
01163   dest->size += len;
01164 }
01165 
01166 /*
01167  * nssASN1_EncodeItem
01168  *
01169  * There must be a better name.  If the optional arena argument is
01170  * non-null, it'll be used for the space.  If the optional rvOpt is
01171  * non-null, it'll be the return value-- if it is null, a new one
01172  * will be allocated.
01173  *
01174  * The error may be one of the following values:
01175  *  NSS_ERROR_NO_MEMORY
01176  *  NSS_ERROR_INVALID_ARENA
01177  *  NSS_ERROR_INVALID_POINTER
01178  *  NSS_ERROR_ENCODING_NOT_SUPPORTED
01179  *
01180  * Return value:
01181  *  NULL upon error
01182  *  A valid pointer to an NSSDER upon success
01183  */
01184 
01185 NSS_IMPLEMENT NSSDER *
01186 nssASN1_EncodeItem
01187 (
01188   NSSArena *arenaOpt,
01189   NSSDER *rvOpt,
01190   const void *source,
01191   const nssASN1Template template[],
01192   NSSASN1EncodingType encoding
01193 )
01194 {
01195   NSSDER *rv;
01196   PRUint32 len = 0;
01197   PRStatus status;
01198 
01199 #ifdef DEBUG
01200   if( (NSSArena *)NULL != arenaOpt ) {
01201     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
01202       return (NSSDER *)NULL;
01203     }
01204   }
01205 
01206   if( (void *)NULL == source ) {
01207     nss_SetError(NSS_ERROR_INVALID_POINTER);
01208     return (NSSDER *)NULL;
01209   }
01210 
01211   if( (nssASN1Template *)NULL == template ) {
01212     nss_SetError(NSS_ERROR_INVALID_POINTER);
01213     return (NSSDER *)NULL;
01214   }
01215 #endif /* DEBUG */
01216 
01217   status = nssASN1_Encode(source, template, encoding, 
01218                           (nssASN1EncoderWriteFunction *)nssasn1_encode_item_count, 
01219                           &len);
01220   if( PR_SUCCESS != status ) {
01221     return (NSSDER *)NULL;
01222   }
01223 
01224   if( (NSSDER *)NULL == rvOpt ) {
01225     rv = nss_ZNEW(arenaOpt, NSSDER);
01226     if( (NSSDER *)NULL == rv ) {
01227       return (NSSDER *)NULL;
01228     }
01229   } else {
01230     rv = rvOpt;
01231   }
01232 
01233   rv->size = len;
01234   rv->data = nss_ZAlloc(arenaOpt, len);
01235   if( (void *)NULL == rv->data ) {
01236     if( (NSSDER *)NULL == rvOpt ) {
01237       nss_ZFreeIf(rv);
01238     }
01239     return (NSSDER *)NULL;
01240   }
01241 
01242   rv->size = 0; /* for nssasn1_encode_item_store */
01243 
01244   status = nssASN1_Encode(source, template, encoding,
01245                           (nssASN1EncoderWriteFunction *)nssasn1_encode_item_store, 
01246                           rv);
01247   if( PR_SUCCESS != status ) {
01248     nss_ZFreeIf(rv->data);
01249     if( (NSSDER *)NULL == rvOpt ) {
01250       nss_ZFreeIf(rv);
01251     }
01252     return (NSSDER *)NULL;
01253   }
01254 
01255   PR_ASSERT(rv->size == len);
01256 
01257   return rv;
01258 }
01259 
01260 /*
01261  * nssASN1_CreatePRUint32FromBER
01262  *
01263  */
01264 
01265 NSS_IMPLEMENT PRStatus
01266 nssASN1_CreatePRUint32FromBER
01267 (
01268   NSSBER *encoded,
01269   PRUint32 *pResult
01270 )
01271 {
01272   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
01273   return PR_FALSE;
01274 }
01275 
01276 /*
01277  * nssASN1_GetDERFromPRUint32
01278  *
01279  */
01280 
01281 NSS_EXTERN NSSDER *
01282 nssASN1_GetDERFromPRUint32
01283 (
01284   NSSArena *arenaOpt,
01285   NSSDER *rvOpt,
01286   PRUint32 value
01287 )
01288 {
01289   NSSDER *rv;
01290   PLArenaPool *hack = (PLArenaPool *)arenaOpt;
01291   SECItem *item;
01292 
01293 #ifdef DEBUG
01294   if( (NSSArena *)NULL != arenaOpt ) {
01295     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
01296       return (NSSDER *)NULL;
01297     }
01298   }
01299 #endif /* DEBUG */
01300 
01301   if( (NSSDER *)NULL == rvOpt ) {
01302     rv = nss_ZNEW(arenaOpt, NSSDER);
01303     if( (NSSDER *)NULL == rv ) {
01304       return (NSSDER *)NULL;
01305     }
01306   } else {
01307     rv = rvOpt;
01308   }
01309 
01310   item = SEC_ASN1EncodeUnsignedInteger(hack, (SECItem *)rv, value);
01311   if( (SECItem *)NULL == item ) {
01312     if( (NSSDER *)NULL == rvOpt ) {
01313       (void)nss_ZFreeIf(rv);
01314     }
01315 
01316     nss_SetError(PORT_GetError()); /* ugly */
01317     return (NSSDER *)NULL;
01318   }
01319 
01320   /* 
01321    * I happen to know that these things look alike.. but I'm only
01322    * doing it for these "temporary" wrappers.  This is an evil thing.
01323    */
01324   return (NSSDER *)item;
01325 }
01326 
01327 /*himom*/
01328 NSS_IMPLEMENT PRStatus
01329 nssASN1_CreatePRInt32FromBER
01330 (
01331   NSSBER *encoded,
01332   PRInt32 *pResult
01333 )
01334 {
01335   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
01336   return PR_FALSE;
01337 }
01338 
01339 /*
01340  * nssASN1_GetDERFromPRInt32
01341  *
01342  */
01343 
01344 NSS_IMPLEMENT NSSDER *
01345 nssASN1_GetDERFromPRInt32
01346 (
01347   NSSArena *arenaOpt,
01348   NSSDER *rvOpt,
01349   PRInt32 value
01350 )
01351 {
01352   NSSDER *rv;
01353   PLArenaPool *hack = (PLArenaPool *)arenaOpt;
01354   SECItem *item;
01355 
01356 #ifdef DEBUG
01357   if( (NSSArena *)NULL != arenaOpt ) {
01358     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
01359       return (NSSDER *)NULL;
01360     }
01361   }
01362 #endif /* DEBUG */
01363 
01364   if( (NSSDER *)NULL == rvOpt ) {
01365     rv = nss_ZNEW(arenaOpt, NSSDER);
01366     if( (NSSDER *)NULL == rv ) {
01367       return (NSSDER *)NULL;
01368     }
01369   } else {
01370     rv = rvOpt;
01371   }
01372 
01373   item = SEC_ASN1EncodeInteger(hack, (SECItem *)rv, value);
01374   if( (SECItem *)NULL == item ) {
01375     if( (NSSDER *)NULL == rvOpt ) {
01376       (void)nss_ZFreeIf(rv);
01377     }
01378 
01379     nss_SetError(PORT_GetError()); /* ugly */
01380     return (NSSDER *)NULL;
01381   }
01382 
01383   /* 
01384    * I happen to know that these things look alike.. but I'm only
01385    * doing it for these "temporary" wrappers.  This is an evil thing.
01386    */
01387   return (NSSDER *)item;
01388 }
01389 
01390 /*
01391  * Generic Templates
01392  * One for each of the simple types, plus a special one for ANY, plus:
01393  *     - a pointer to each one of those
01394  *     - a set of each one of those
01395  *
01396  * Note that these are alphabetical (case insensitive); please add new
01397  * ones in the appropriate place.
01398  */
01399 
01400 const nssASN1Template *nssASN1Template_Any =                             (nssASN1Template *)SEC_AnyTemplate;
01401 const nssASN1Template *nssASN1Template_BitString =                       (nssASN1Template *)SEC_BitStringTemplate;
01402 const nssASN1Template *nssASN1Template_BMPString =                       (nssASN1Template *)SEC_BMPStringTemplate;
01403 const nssASN1Template *nssASN1Template_Boolean =                         (nssASN1Template *)SEC_BooleanTemplate;
01404 const nssASN1Template *nssASN1Template_Enumerated =                      (nssASN1Template *)SEC_EnumeratedTemplate;
01405 const nssASN1Template *nssASN1Template_GeneralizedTime =                 (nssASN1Template *)SEC_GeneralizedTimeTemplate;
01406 const nssASN1Template *nssASN1Template_IA5String =                       (nssASN1Template *)SEC_IA5StringTemplate;
01407 const nssASN1Template *nssASN1Template_Integer =                         (nssASN1Template *)SEC_IntegerTemplate;
01408 const nssASN1Template *nssASN1Template_Null =                            (nssASN1Template *)SEC_NullTemplate;
01409 const nssASN1Template *nssASN1Template_ObjectID =                        (nssASN1Template *)SEC_ObjectIDTemplate;
01410 const nssASN1Template *nssASN1Template_OctetString =                     (nssASN1Template *)SEC_OctetStringTemplate;
01411 const nssASN1Template *nssASN1Template_PrintableString =                 (nssASN1Template *)SEC_PrintableStringTemplate;
01412 const nssASN1Template *nssASN1Template_T61String =                       (nssASN1Template *)SEC_T61StringTemplate;
01413 const nssASN1Template *nssASN1Template_UniversalString =                 (nssASN1Template *)SEC_UniversalStringTemplate;
01414 const nssASN1Template *nssASN1Template_UTCTime =                         (nssASN1Template *)SEC_UTCTimeTemplate;
01415 const nssASN1Template *nssASN1Template_UTF8String =                      (nssASN1Template *)SEC_UTF8StringTemplate;
01416 const nssASN1Template *nssASN1Template_VisibleString =                   (nssASN1Template *)SEC_VisibleStringTemplate;
01417 
01418 const nssASN1Template *nssASN1Template_PointerToAny =                    (nssASN1Template *)SEC_PointerToAnyTemplate;
01419 const nssASN1Template *nssASN1Template_PointerToBitString =              (nssASN1Template *)SEC_PointerToBitStringTemplate;
01420 const nssASN1Template *nssASN1Template_PointerToBMPString =              (nssASN1Template *)SEC_PointerToBMPStringTemplate;
01421 const nssASN1Template *nssASN1Template_PointerToBoolean =                (nssASN1Template *)SEC_PointerToBooleanTemplate;
01422 const nssASN1Template *nssASN1Template_PointerToEnumerated =             (nssASN1Template *)SEC_PointerToEnumeratedTemplate;
01423 const nssASN1Template *nssASN1Template_PointerToGeneralizedTime =        (nssASN1Template *)SEC_PointerToGeneralizedTimeTemplate;
01424 const nssASN1Template *nssASN1Template_PointerToIA5String =              (nssASN1Template *)SEC_PointerToIA5StringTemplate;
01425 const nssASN1Template *nssASN1Template_PointerToInteger =                (nssASN1Template *)SEC_PointerToIntegerTemplate;
01426 const nssASN1Template *nssASN1Template_PointerToNull =                   (nssASN1Template *)SEC_PointerToNullTemplate;
01427 const nssASN1Template *nssASN1Template_PointerToObjectID =               (nssASN1Template *)SEC_PointerToObjectIDTemplate;
01428 const nssASN1Template *nssASN1Template_PointerToOctetString =            (nssASN1Template *)SEC_PointerToOctetStringTemplate;
01429 const nssASN1Template *nssASN1Template_PointerToPrintableString =        (nssASN1Template *)SEC_PointerToPrintableStringTemplate;
01430 const nssASN1Template *nssASN1Template_PointerToT61String =              (nssASN1Template *)SEC_PointerToT61StringTemplate;
01431 const nssASN1Template *nssASN1Template_PointerToUniversalString =        (nssASN1Template *)SEC_PointerToUniversalStringTemplate;
01432 const nssASN1Template *nssASN1Template_PointerToUTCTime =                (nssASN1Template *)SEC_PointerToUTCTimeTemplate;
01433 const nssASN1Template *nssASN1Template_PointerToUTF8String =             (nssASN1Template *)SEC_PointerToUTF8StringTemplate;
01434 const nssASN1Template *nssASN1Template_PointerToVisibleString =          (nssASN1Template *)SEC_PointerToVisibleStringTemplate;
01435 
01436 const nssASN1Template *nssASN1Template_SetOfAny =                        (nssASN1Template *)SEC_SetOfAnyTemplate;
01437 const nssASN1Template *nssASN1Template_SetOfBitString =                  (nssASN1Template *)SEC_SetOfBitStringTemplate;
01438 const nssASN1Template *nssASN1Template_SetOfBMPString =                  (nssASN1Template *)SEC_SetOfBMPStringTemplate;
01439 const nssASN1Template *nssASN1Template_SetOfBoolean =                    (nssASN1Template *)SEC_SetOfBooleanTemplate;
01440 const nssASN1Template *nssASN1Template_SetOfEnumerated =                 (nssASN1Template *)SEC_SetOfEnumeratedTemplate;
01441 const nssASN1Template *nssASN1Template_SetOfGeneralizedTime =            (nssASN1Template *)SEC_SetOfGeneralizedTimeTemplate;
01442 const nssASN1Template *nssASN1Template_SetOfIA5String =                  (nssASN1Template *)SEC_SetOfIA5StringTemplate;
01443 const nssASN1Template *nssASN1Template_SetOfInteger =                    (nssASN1Template *)SEC_SetOfIntegerTemplate;
01444 const nssASN1Template *nssASN1Template_SetOfNull =                       (nssASN1Template *)SEC_SetOfNullTemplate;
01445 const nssASN1Template *nssASN1Template_SetOfObjectID =                   (nssASN1Template *)SEC_SetOfObjectIDTemplate;
01446 const nssASN1Template *nssASN1Template_SetOfOctetString =                (nssASN1Template *)SEC_SetOfOctetStringTemplate;
01447 const nssASN1Template *nssASN1Template_SetOfPrintableString =            (nssASN1Template *)SEC_SetOfPrintableStringTemplate;
01448 const nssASN1Template *nssASN1Template_SetOfT61String =                  (nssASN1Template *)SEC_SetOfT61StringTemplate;
01449 const nssASN1Template *nssASN1Template_SetOfUniversalString =            (nssASN1Template *)SEC_SetOfUniversalStringTemplate;
01450 const nssASN1Template *nssASN1Template_SetOfUTCTime =                    (nssASN1Template *)SEC_SetOfUTCTimeTemplate;
01451 const nssASN1Template *nssASN1Template_SetOfUTF8String =                 (nssASN1Template *)SEC_SetOfUTF8StringTemplate;
01452 const nssASN1Template *nssASN1Template_SetOfVisibleString =              (nssASN1Template *)SEC_SetOfVisibleStringTemplate;
01453 
01454 /*
01455  *
01456  */
01457 
01458 NSS_IMPLEMENT NSSUTF8 *
01459 nssUTF8_CreateFromBER
01460 (
01461   NSSArena *arenaOpt,
01462   nssStringType type,
01463   NSSBER *berData
01464 )
01465 {
01466   NSSUTF8 *rv = NULL;
01467   PRUint8 tag;
01468   NSSArena *a;
01469   NSSItem in;
01470   NSSItem out;
01471   PRStatus st;
01472   const nssASN1Template *templ;
01473 
01474 #ifdef NSSDEBUG
01475   if( (NSSArena *)NULL != arenaOpt ) {
01476     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
01477       return (NSSUTF8 *)NULL;
01478     }
01479   }
01480 
01481   if( (NSSBER *)NULL == berData ) {
01482     nss_SetError(NSS_ERROR_INVALID_POINTER);
01483     return (NSSUTF8 *)NULL;
01484   }
01485 
01486   if( (void *)NULL == berData->data ) {
01487     nss_SetError(NSS_ERROR_INVALID_POINTER);
01488     return (NSSUTF8 *)NULL;
01489   }
01490 #endif /* NSSDEBUG */
01491 
01492   a = NSSArena_Create();
01493   if( (NSSArena *)NULL == a ) {
01494     return (NSSUTF8 *)NULL;
01495   }
01496 
01497   in = *berData;
01498 
01499   /*
01500    * By the way, at first I succumbed to the temptation to make
01501    * this an incestuous nested switch statement.  Count yourself
01502    * lucky I cleaned it up.
01503    */
01504 
01505   switch( type ) {
01506   case nssStringType_DirectoryString:
01507     /*
01508      * draft-ietf-pkix-ipki-part1-11 says in part:
01509      *
01510      * DirectoryString { INTEGER:maxSize } ::= CHOICE {
01511      *   teletexString           TeletexString (SIZE (1..maxSize)),
01512      *   printableString         PrintableString (SIZE (1..maxSize)),
01513      *   universalString         UniversalString (SIZE (1..maxSize)),
01514      *   bmpString               BMPString (SIZE(1..maxSize)),
01515      *   utf8String              UTF8String (SIZE(1..maxSize))
01516      *                       }
01517      *
01518      * The tags are:
01519      *  TeletexString       UNIVERSAL 20
01520      *  PrintableString     UNIVERSAL 19
01521      *  UniversalString     UNIVERSAL 28
01522      *  BMPString           UNIVERSAL 30
01523      *  UTF8String          UNIVERSAL 12
01524      *
01525      * "UNIVERSAL" tags have bits 8 and 7 zero, bit 6 is zero for
01526      * primitive encodings, and if the tag value is less than 30,
01527      * the tag value is directly encoded in bits 5 through 1.
01528      */
01529     in.data = (void *)&(((PRUint8 *)berData->data)[1]);
01530     in.size = berData->size-1;
01531     
01532     tag = *(PRUint8 *)berData->data;
01533     switch( tag & nssASN1_TAGNUM_MASK ) {
01534     case 20:
01535       /*
01536        * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
01537        * below) but is T61 a suitable value for "Latin-1"?
01538        */
01539       templ = nssASN1Template_T61String;
01540       type = nssStringType_TeletexString;
01541       break;
01542     case 19:
01543       templ = nssASN1Template_PrintableString;
01544       type = nssStringType_PrintableString;
01545       break;
01546     case 28:
01547       templ = nssASN1Template_UniversalString;
01548       type = nssStringType_UniversalString;
01549       break;
01550     case 30:
01551       templ = nssASN1Template_BMPString;
01552       type = nssStringType_BMPString;
01553       break;
01554     case 12:
01555       templ = nssASN1Template_UTF8String;
01556       type = nssStringType_UTF8String;
01557       break;
01558     default:
01559       nss_SetError(NSS_ERROR_INVALID_POINTER); /* "pointer"? */
01560       (void)NSSArena_Destroy(a);
01561       return (NSSUTF8 *)NULL;
01562     }
01563 
01564     break;
01565 
01566   case nssStringType_TeletexString:
01567     /*
01568      * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
01569      * below) but is T61 a suitable value for "Latin-1"?
01570      */
01571     templ = nssASN1Template_T61String;
01572     break;
01573    
01574   case nssStringType_PrintableString:
01575     templ = nssASN1Template_PrintableString;
01576     break;
01577 
01578   case nssStringType_UniversalString:
01579     templ = nssASN1Template_UniversalString;
01580     break;
01581 
01582   case nssStringType_BMPString:
01583     templ = nssASN1Template_BMPString;
01584     break;
01585 
01586   case nssStringType_UTF8String:
01587     templ = nssASN1Template_UTF8String;
01588     break;
01589 
01590   case nssStringType_PHGString:
01591     templ = nssASN1Template_IA5String;
01592     break;
01593 
01594   default:
01595     nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
01596     (void)NSSArena_Destroy(a);
01597     return (NSSUTF8 *)NULL;
01598   }
01599     
01600   st = nssASN1_DecodeBER(a, &out, templ, &in);
01601   
01602   if( PR_SUCCESS == st ) {
01603     rv = nssUTF8_Create(arenaOpt, type, out.data, out.size);
01604   }
01605   (void)NSSArena_Destroy(a);
01606   
01607   return rv;
01608 }
01609 
01610 NSS_EXTERN NSSDER *
01611 nssUTF8_GetDEREncoding
01612 (
01613   NSSArena *arenaOpt,
01614   nssStringType type,
01615   const NSSUTF8 *string
01616 )
01617 {
01618   NSSDER *rv = (NSSDER *)NULL;
01619   NSSItem str;
01620   NSSDER *der;
01621   const nssASN1Template *templ;
01622   NSSArena *a;
01623 
01624 #ifdef NSSDEBUG
01625   if( (NSSArena *)NULL != arenaOpt ) {
01626     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
01627       return (NSSDER *)NULL;
01628     }
01629   }
01630 
01631   if( (const NSSUTF8 *)NULL == string ) {
01632     nss_SetError(NSS_ERROR_INVALID_POINTER);
01633     return (NSSDER *)NULL;
01634   }
01635 #endif /* NSSDEBUG */
01636 
01637   str.data = (void *)string;
01638   str.size = nssUTF8_Size(string, (PRStatus *)NULL);
01639   if( 0 == str.size ) {
01640     return (NSSDER *)NULL;
01641   }
01642 
01643   a = NSSArena_Create();
01644   if( (NSSArena *)NULL == a ) {
01645     return (NSSDER *)NULL;
01646   }
01647 
01648   switch( type ) {
01649   case nssStringType_DirectoryString:
01650     {
01651       NSSDER *utf;
01652       PRUint8 *c;
01653 
01654       utf = nssASN1_EncodeItem(a, (NSSDER *)NULL, &str, 
01655                                nssASN1Template_UTF8String,
01656                                NSSASN1DER);
01657       if( (NSSDER *)NULL == utf ) {
01658         (void)NSSArena_Destroy(a);
01659         return (NSSDER *)NULL;
01660       }
01661 
01662       rv = nss_ZNEW(arenaOpt, NSSDER);
01663       if( (NSSDER *)NULL == rv ) {
01664         (void)NSSArena_Destroy(a);
01665         return (NSSDER *)NULL;
01666       }
01667 
01668       rv->size = utf->size + 1;
01669       rv->data = nss_ZAlloc(arenaOpt, rv->size);
01670       if( (void *)NULL == rv->data ) {
01671         (void)nss_ZFreeIf(rv);
01672         (void)NSSArena_Destroy(a);
01673         return (NSSDER *)NULL;
01674       }
01675       
01676       c = (PRUint8 *)rv->data;
01677       (void)nsslibc_memcpy(&c[1], utf->data, utf->size);
01678       *c = 12; /* UNIVERSAL primitive encoding tag for UTF8String */
01679 
01680       (void)NSSArena_Destroy(a);
01681       return rv;
01682     }
01683   case nssStringType_TeletexString:
01684     /*
01685      * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
01686      * below) but is T61 a suitable value for "Latin-1"?
01687      */
01688     templ = nssASN1Template_T61String;
01689     break;
01690   case nssStringType_PrintableString:
01691     templ = nssASN1Template_PrintableString;
01692     break;
01693 
01694   case nssStringType_UniversalString:
01695     templ = nssASN1Template_UniversalString;
01696     break;
01697 
01698   case nssStringType_BMPString:
01699     templ = nssASN1Template_BMPString;
01700     break;
01701 
01702   case nssStringType_UTF8String:
01703     templ = nssASN1Template_UTF8String;
01704     break;
01705 
01706   case nssStringType_PHGString:
01707     templ = nssASN1Template_IA5String;
01708     break;
01709 
01710   default:
01711     nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
01712     (void)NSSArena_Destroy(a);
01713     return (NSSDER *)NULL;
01714   }
01715 
01716   der = nssUTF8_GetDEREncoding(a, type, string);
01717   if( (NSSItem *)NULL == der ) {
01718     (void)NSSArena_Destroy(a);
01719     return (NSSDER *)NULL;
01720   }
01721 
01722   rv = nssASN1_EncodeItem(arenaOpt, (NSSDER *)NULL, der, templ, NSSASN1DER);
01723   if( (NSSDER *)NULL == rv ) {
01724     (void)NSSArena_Destroy(a);
01725     return (NSSDER *)NULL;
01726   }
01727 
01728   (void)NSSArena_Destroy(a);
01729   return rv;
01730 }