asn1.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:43k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* 
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #ifdef DEBUG
  34. static const char CVS_ID[] = "@(#) $RCSfile: asn1.c,v $ $Revision: 1.1 $ $Date: 2000/03/31 19:54:49 $ $Name: NSS_3_1_1_RTM $";
  35. #endif /* DEBUG */
  36. /*
  37.  * asn1.c
  38.  *
  39.  * At this point in time, this file contains the NSS wrappers for
  40.  * the old "SEC" ASN.1 encoder/decoder stuff.
  41.  */
  42. #ifndef ASN1M_H
  43. #include "asn1m.h"
  44. #endif /* ASN1M_H */
  45. #include "plarena.h"
  46. #include "secasn1.h"
  47. /*
  48.  * The pointer-tracking stuff
  49.  */
  50. #ifdef DEBUG
  51. extern const NSSError NSS_ERROR_INTERNAL_ERROR;
  52. static nssPointerTracker decoder_pointer_tracker;
  53. static PRStatus
  54. decoder_add_pointer
  55. (
  56.   const nssASN1Decoder *decoder
  57. )
  58. {
  59.   PRStatus rv;
  60.   rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
  61.   if( PR_SUCCESS != rv ) {
  62.     return rv;
  63.   }
  64.   rv = nssPointerTracker_add(&decoder_pointer_tracker, decoder);
  65.   if( PR_SUCCESS != rv ) {
  66.     NSSError e = NSS_GetError();
  67.     if( NSS_ERROR_NO_MEMORY != e ) {
  68.       nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  69.     }
  70.     return rv;
  71.   }
  72.   return PR_SUCCESS;
  73. }
  74. static PRStatus
  75. decoder_remove_pointer
  76. (
  77.   const nssASN1Decoder *decoder
  78. )
  79. {
  80.   PRStatus rv;
  81.   rv = nssPointerTracker_remove(&decoder_pointer_tracker, decoder);
  82.   if( PR_SUCCESS != rv ) {
  83.     nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  84.   }
  85.   return rv;
  86. }
  87. /*
  88.  * nssASN1Decoder_verify
  89.  *
  90.  * This routine is only available in debug builds.
  91.  *
  92.  * If the specified pointer is a valid pointer to an nssASN1Decoder
  93.  * object, this routine will return PR_SUCCESS.  Otherwise, it will 
  94.  * put an error on the error stack and return PR_FAILURE.
  95.  *
  96.  * The error may be one of the following values:
  97.  *  NSS_ERROR_INVALID_ASN1DECODER
  98.  *
  99.  * Return value:
  100.  *  PR_FAILURE upon error
  101.  *  PR_SUCCESS upon success
  102.  */
  103. NSS_IMPLEMENT PRStatus
  104. nssASN1Decoder_verify
  105. (
  106.   nssASN1Decoder *decoder
  107. )
  108. {
  109.   PRStatus rv;
  110.   rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
  111.   if( PR_SUCCESS != rv ) {
  112.     return PR_FAILURE;
  113.   }
  114.   rv = nssPointerTracker_verify(&decoder_pointer_tracker, decoder);
  115.   if( PR_SUCCESS != rv ) {
  116.     nss_SetError(NSS_ERROR_INVALID_ASN1DECODER);
  117.     return PR_FAILURE;
  118.   }
  119.   return PR_SUCCESS;
  120. }
  121. static nssPointerTracker encoder_pointer_tracker;
  122. static PRStatus
  123. encoder_add_pointer
  124. (
  125.   const nssASN1Encoder *encoder
  126. )
  127. {
  128.   PRStatus rv;
  129.   rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
  130.   if( PR_SUCCESS != rv ) {
  131.     return rv;
  132.   }
  133.   rv = nssPointerTracker_add(&encoder_pointer_tracker, encoder);
  134.   if( PR_SUCCESS != rv ) {
  135.     NSSError e = NSS_GetError();
  136.     if( NSS_ERROR_NO_MEMORY != e ) {
  137.       nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  138.     }
  139.     return rv;
  140.   }
  141.   return PR_SUCCESS;
  142. }
  143. static PRStatus
  144. encoder_remove_pointer
  145. (
  146.   const nssASN1Encoder *encoder
  147. )
  148. {
  149.   PRStatus rv;
  150.   rv = nssPointerTracker_remove(&encoder_pointer_tracker, encoder);
  151.   if( PR_SUCCESS != rv ) {
  152.     nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  153.   }
  154.   return rv;
  155. }
  156. /*
  157.  * nssASN1Encoder_verify
  158.  *
  159.  * This routine is only available in debug builds.
  160.  *
  161.  * If the specified pointer is a valid pointer to an nssASN1Encoder
  162.  * object, this routine will return PR_SUCCESS.  Otherwise, it will 
  163.  * put an error on the error stack and return PR_FAILURE.
  164.  *
  165.  * The error may be one of the following values:
  166.  *  NSS_ERROR_INVALID_ASN1ENCODER
  167.  *
  168.  * Return value:
  169.  *  PR_FAILURE upon error
  170.  *  PR_SUCCESS upon success
  171.  */
  172. NSS_IMPLEMENT PRStatus
  173. nssASN1Encoder_verify
  174. (
  175.   nssASN1Encoder *encoder
  176. )
  177. {
  178.   PRStatus rv;
  179.   rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
  180.   if( PR_SUCCESS != rv ) {
  181.     return PR_FAILURE;
  182.   }
  183.   rv = nssPointerTracker_verify(&encoder_pointer_tracker, encoder);
  184.   if( PR_SUCCESS != rv ) {
  185.     nss_SetError(NSS_ERROR_INVALID_ASN1ENCODER);
  186.     return PR_FAILURE;
  187.   }
  188.   return PR_SUCCESS;
  189. }
  190. #endif /* DEBUG */
  191. /*
  192.  * nssASN1Decoder_Create
  193.  *
  194.  * This routine creates an ASN.1 Decoder, which will use the specified
  195.  * template to decode a datastream into the specified destination
  196.  * structure.  If the optional arena argument is non-NULL, blah blah 
  197.  * blah.  XXX fgmr Should we include an nssASN1EncodingType argument, 
  198.  * as a hint?  Or is each encoding distinctive?  This routine may 
  199.  * return NULL upon error, in which case an error will have been 
  200.  * placed upon the error stack.
  201.  *
  202.  * The error may be one of the following values:
  203.  *  NSS_ERROR_NO_MEMORY
  204.  *  NSS_ERROR_INVALID_ARENA
  205.  *  NSS_ERROR_INVALID_POINTER
  206.  *  ...
  207.  *
  208.  * Return value:
  209.  *  NULL upon error
  210.  *  A pointer to an ASN.1 Decoder upon success.
  211.  */
  212. NSS_IMPLEMENT nssASN1Decoder *
  213. nssASN1Decoder_Create
  214. (
  215.   NSSArena *arenaOpt,
  216.   void *destination,
  217.   const nssASN1Template template[]
  218. )
  219. {
  220.   SEC_ASN1DecoderContext *rv;
  221.   PLArenaPool *hack = (PLArenaPool *)arenaOpt;
  222. #ifdef DEBUG
  223.   if( (NSSArena *)NULL != arenaOpt ) {
  224.     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
  225.       return (nssASN1Decoder *)NULL;
  226.     }
  227.   }
  228.   /* 
  229.    * May destination be NULL?  I'd think so, since one might
  230.    * have only a filter proc.  But if not, check the pointer here.
  231.    */
  232.   if( (nssASN1Template *)NULL == template ) {
  233.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  234.     return (nssASN1Decoder *)NULL;
  235.   }
  236. #endif /* DEBUG */
  237.   rv = SEC_ASN1DecoderStart(hack, destination, template);
  238.   if( (SEC_ASN1DecoderContext *)NULL == rv ) {
  239.     nss_SetError(PORT_GetError()); /* also evil */
  240.     return (nssASN1Decoder *)NULL;
  241.   }
  242. #ifdef DEBUG
  243.   if( PR_SUCCESS != decoder_add_pointer(rv) ) {
  244.     (void)SEC_ASN1DecoderFinish(rv);
  245.     return (nssASN1Decoder *)NULL;
  246.   }
  247. #endif /* DEBUG */
  248.   return (nssASN1Decoder *)rv;
  249. }
  250. /*
  251.  * nssASN1Decoder_Update
  252.  *
  253.  * This routine feeds data to the decoder.  In the event of an error, 
  254.  * it will place an error on the error stack and return PR_FAILURE.
  255.  *
  256.  * The error may be one of the following values:
  257.  *  NSS_ERROR_NO_MEMORY
  258.  *  NSS_ERROR_INVALID_POINTER
  259.  *  NSS_ERROR_INVALID_ASN1DECODER
  260.  *  NSS_ERROR_INVALID_BER
  261.  *  ...
  262.  *
  263.  * Return value:
  264.  *  PR_FAILURE upon error
  265.  *  PR_SUCCESS upon success.
  266.  */
  267. NSS_IMPLEMENT PRStatus
  268. nssASN1Decoder_Update
  269. (
  270.   nssASN1Decoder *decoder,
  271.   const void *data,
  272.   PRUint32 amount
  273. )
  274. {
  275.   PRStatus rv;
  276. #ifdef DEBUG
  277.   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
  278.     return PR_FAILURE;
  279.   }
  280.   if( (void *)NULL == data ) {
  281.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  282.     return PR_FAILURE;
  283.   }
  284. #endif /* DEBUG */
  285.   rv = SEC_ASN1DecoderUpdate((SEC_ASN1DecoderContext *)decoder, 
  286.                              (const char *)data,
  287.                              (unsigned long)amount);
  288.   if( PR_SUCCESS != rv ) {
  289.     nss_SetError(PORT_GetError()); /* ugly */
  290.     return PR_FAILURE;
  291.   }
  292.   return PR_SUCCESS;
  293. }
  294. /*
  295.  * nssASN1Decoder_Finish
  296.  *
  297.  * This routine finishes the decoding and destroys the decoder.
  298.  * In the event of an error, it will place an error on the error
  299.  * stack and return PR_FAILURE.
  300.  *
  301.  * The error may be one of the following values:
  302.  *  NSS_ERROR_INVALID_ASN1DECODER
  303.  *
  304.  * Return value:
  305.  *  PR_FAILURE upon error
  306.  *  PR_SUCCESS upon success
  307.  */
  308. NSS_IMPLEMENT PRStatus
  309. nssASN1Decoder_Finish
  310. (
  311.   nssASN1Decoder *decoder
  312. )
  313. {
  314.   PRStatus rv;
  315. #ifdef DEBUG
  316.   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
  317.     return PR_FAILURE;
  318.   }
  319. #endif /* DEBUG */
  320.   rv = SEC_ASN1DecoderFinish((SEC_ASN1DecoderContext *)decoder);
  321.   if( PR_SUCCESS != rv ) {
  322.     nss_SetError(PORT_GetError()); /* ugly */
  323.   }
  324. #ifdef DEBUG
  325.   {
  326.     PRStatus rv2 = decoder_remove_pointer(decoder);
  327.     if( PR_SUCCESS == rv ) {
  328.       rv = rv2;
  329.     }
  330.   }
  331. #endif /* DEBUG */
  332.   return rv;
  333. }
  334. /*
  335.  * nssASN1Decoder_SetFilter
  336.  *
  337.  * This routine registers a callback filter routine with the decoder,
  338.  * which will be called blah blah blah.  The specified argument will
  339.  * be passed as-is to the filter routine.  The routine pointer may
  340.  * be NULL, in which case no filter callback will be called.  If the
  341.  * noStore boolean is PR_TRUE, then decoded fields will not be stored
  342.  * in the destination structure specified when the decoder was 
  343.  * created.  This routine returns a PRStatus value; in the event of
  344.  * an error, it will place an error on the error stack and return
  345.  * PR_FAILURE.
  346.  *
  347.  * The error may be one of the following values:
  348.  *  NSS_ERROR_INVALID_ASN1DECODER
  349.  *
  350.  * Return value:
  351.  *  PR_FAILURE upon error
  352.  *  PR_SUCCESS upon success
  353.  */
  354. NSS_IMPLEMENT PRStatus
  355. nssASN1Decoder_SetFilter
  356. (
  357.   nssASN1Decoder *decoder,
  358.   nssASN1DecoderFilterFunction *callback,
  359.   void *argument,
  360.   PRBool noStore
  361. )
  362. {
  363. #ifdef DEBUG
  364.   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
  365.     return PR_FAILURE;
  366.   }
  367. #endif /* DEBUG */
  368.   if( (nssASN1DecoderFilterFunction *)NULL == callback ) {
  369.      SEC_ASN1DecoderClearFilterProc((SEC_ASN1DecoderContext *)decoder);
  370.   } else {
  371.      SEC_ASN1DecoderSetFilterProc((SEC_ASN1DecoderContext *)decoder,
  372.                                   (SEC_ASN1WriteProc)callback,
  373.                                   argument, noStore);
  374.   }
  375.   /* No error returns defined for those routines */
  376.   return PR_SUCCESS;
  377. }
  378. /*
  379.  * nssASN1Decoder_GetFilter
  380.  *
  381.  * If the optional pCallbackOpt argument to this routine is non-null,
  382.  * then the pointer to any callback function established for this
  383.  * decoder with nssASN1Decoder_SetFilter will be stored at the 
  384.  * location indicated by it.  If the optional pArgumentOpt
  385.  * pointer is non-null, the filter's closure argument will be stored
  386.  * there.  If the optional pNoStoreOpt pointer is non-null, the
  387.  * noStore value specified when setting the filter will be stored
  388.  * there.  This routine returns a PRStatus value; in the event of
  389.  * an error it will place an error on the error stack and return
  390.  * PR_FAILURE.
  391.  *
  392.  * The error may be one of the following values:
  393.  *  NSS_ERROR_INVALID_ASN1DECODER
  394.  *
  395.  * Return value:
  396.  *  PR_FAILURE upon error
  397.  *  PR_SUCCESS upon success
  398.  */
  399. extern const NSSError NSS_ERROR_INTERNAL_ERROR;
  400. NSS_IMPLEMENT PRStatus
  401. nssASN1Decoder_GetFilter
  402. (
  403.   nssASN1Decoder *decoder,
  404.   nssASN1DecoderFilterFunction **pCallbackOpt,
  405.   void **pArgumentOpt,
  406.   PRBool *pNoStoreOpt
  407. )
  408. {
  409. #ifdef DEBUG
  410.   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
  411.     return PR_FAILURE;
  412.   }
  413. #endif /* DEBUG */
  414.   if( (nssASN1DecoderFilterFunction **)NULL != pCallbackOpt ) {
  415.     *pCallbackOpt = (nssASN1DecoderFilterFunction *)NULL;
  416.   }
  417.   if( (void **)NULL != pArgumentOpt ) {
  418.     *pArgumentOpt = (void *)NULL;
  419.   }
  420.   if( (PRBool *)NULL != pNoStoreOpt ) {
  421.     *pNoStoreOpt = PR_FALSE;
  422.   }
  423.   /* Error because it's unimplemented */
  424.   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  425.   return PR_FAILURE;
  426. }
  427. /*
  428.  * nssASN1Decoder_SetNotify
  429.  *
  430.  * This routine registers a callback notify routine with the decoder,
  431.  * which will be called whenever.. The specified argument will be
  432.  * passed as-is to the notify routine.  The routine pointer may be
  433.  * NULL, in which case no notify routine will be called.  This routine
  434.  * returns a PRStatus value; in the event of an error it will place
  435.  * an error on the error stack and return PR_FAILURE.
  436.  *
  437.  * The error may be one of the following values:
  438.  *  NSS_ERROR_INVALID_ASN1DECODER
  439.  *
  440.  * Return value:
  441.  *  PR_FAILURE upon error
  442.  *  PR_SUCCESS upon success
  443.  */
  444. NSS_IMPLEMENT PRStatus
  445. nssASN1Decoder_SetNotify
  446. (
  447.   nssASN1Decoder *decoder,
  448.   nssASN1NotifyFunction *callback,
  449.   void *argument
  450. )
  451. {
  452. #ifdef DEBUG
  453.   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
  454.     return PR_FAILURE;
  455.   }
  456. #endif /* DEBUG */
  457.   if( (nssASN1NotifyFunction *)NULL == callback ) {
  458.     SEC_ASN1DecoderClearNotifyProc((SEC_ASN1DecoderContext *)decoder);
  459.   } else {
  460.     SEC_ASN1DecoderSetNotifyProc((SEC_ASN1DecoderContext *)decoder,
  461.                                  (SEC_ASN1NotifyProc)callback,
  462.                                  argument);
  463.   }
  464.   /* No error returns defined for those routines */
  465.   return PR_SUCCESS;
  466. }
  467. /*
  468.  * nssASN1Decoder_GetNotify
  469.  *
  470.  * If the optional pCallbackOpt argument to this routine is non-null,
  471.  * then the pointer to any callback function established for this
  472.  * decoder with nssASN1Decoder_SetNotify will be stored at the 
  473.  * location indicated by it.  If the optional pArgumentOpt pointer is
  474.  * non-null, the filter's closure argument will be stored there.
  475.  * This routine returns a PRStatus value; in the event of an error it
  476.  * will place an error on the error stack and return PR_FAILURE.
  477.  *
  478.  * The error may be one of the following values:
  479.  *  NSS_ERROR_INVALID_ASN1DECODER
  480.  *
  481.  * Return value:
  482.  *  PR_FAILURE upon error
  483.  *  PR_SUCCESS upon success
  484.  */
  485. NSS_IMPLEMENT PRStatus
  486. nssASN1Decoder_GetNotify
  487. (
  488.   nssASN1Decoder *decoder,
  489.   nssASN1NotifyFunction **pCallbackOpt,
  490.   void **pArgumentOpt
  491. )
  492. {
  493. #ifdef DEBUG
  494.   if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
  495.     return PR_FAILURE;
  496.   }
  497. #endif /* DEBUG */
  498.   if( (nssASN1NotifyFunction **)NULL != pCallbackOpt ) {
  499.     *pCallbackOpt = (nssASN1NotifyFunction *)NULL;
  500.   }
  501.   if( (void **)NULL != pArgumentOpt ) {
  502.     *pArgumentOpt = (void *)NULL;
  503.   }
  504.   /* Error because it's unimplemented */
  505.   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  506.   return PR_FAILURE;
  507. }
  508. /*
  509.  * nssASN1_Decode
  510.  *
  511.  * This routine will decode the specified data into the specified
  512.  * destination structure, as specified by the specified template.
  513.  * This routine returns a PRStatus value; in the event of an error
  514.  * it will place an error on the error stack and return PR_FAILURE.
  515.  *
  516.  * The error may be one of the following values:
  517.  *  NSS_ERROR_NO_MEMORY
  518.  *  NSS_ERROR_INVALID_ARENA
  519.  *  NSS_ERROR_INVALID_POINTER
  520.  *  NSS_ERROR_INVALID_BER
  521.  *
  522.  * Return value:
  523.  *  PR_FAILURE upon error
  524.  *  PR_SUCCESS upon success
  525.  */
  526. NSS_IMPLEMENT PRStatus
  527. nssASN1_Decode
  528. (
  529.   NSSArena *arenaOpt,
  530.   void *destination,
  531.   const nssASN1Template template[],
  532.   const void *berData,
  533.   PRUint32 amount
  534. )
  535. {
  536.   PRStatus rv;
  537.   nssASN1Decoder *decoder;
  538.   /* This call will do our pointer-checking for us! */
  539.   decoder = nssASN1Decoder_Create(arenaOpt, destination, template);
  540.   if( (nssASN1Decoder *)NULL == decoder ) {
  541.     return PR_FAILURE;
  542.   }
  543.   rv = nssASN1Decoder_Update(decoder, berData, amount);
  544.   if( PR_SUCCESS != nssASN1Decoder_Finish(decoder) ) {
  545.     rv = PR_FAILURE;
  546.   }
  547.   return rv;
  548. }
  549. /*
  550.  * nssASN1_DecodeBER
  551.  *
  552.  * This routine will decode the data in the specified NSSBER
  553.  * into the destination structure, as specified by the template.
  554.  * This routine returns a PRStatus value; in the event of an error
  555.  * it will place an error on the error stack and return PR_FAILURE.
  556.  *
  557.  * The error may be one of the following values:
  558.  *  NSS_ERROR_NO_MEMORY
  559.  *  NSS_ERROR_INVALID_ARENA
  560.  *  NSS_ERROR_INVALID_POINTER
  561.  *  NSS_ERROR_INVALID_NSSBER
  562.  *  NSS_ERROR_INVALID_BER
  563.  *
  564.  * Return value:
  565.  *  PR_FAILURE upon error
  566.  *  PR_SUCCESS upon success
  567.  */
  568. NSS_IMPLEMENT PRStatus
  569. nssASN1_DecodeBER
  570. (
  571.   NSSArena *arenaOpt,
  572.   void *destination,
  573.   const nssASN1Template template[],
  574.   const NSSBER *data
  575. )
  576. {
  577.   return nssASN1_Decode(arenaOpt, destination, template, 
  578.                         data->data, data->size);
  579. }
  580. /*
  581.  * nssASN1Encoder_Create
  582.  *
  583.  * This routine creates an ASN.1 Encoder, blah blah blah.  This 
  584.  * may return NULL upon error, in which case an error will have been
  585.  * placed on the error stack.
  586.  *
  587.  * The error may be one of the following values:
  588.  *  NSS_ERROR_NO_MEMORY
  589.  *  NSS_ERROR_INVALID_ARENA
  590.  *  NSS_ERROR_INVALID_POINTER
  591.  *  ...
  592.  *
  593.  * Return value:
  594.  *  NULL upon error
  595.  *  A pointer to an ASN.1 Encoder upon success
  596.  */
  597. NSS_IMPLEMENT nssASN1Encoder *
  598. nssASN1Encoder_Create
  599. (
  600.   const void *source,
  601.   const nssASN1Template template[],
  602.   NSSASN1EncodingType encoding,
  603.   nssASN1EncoderWriteFunction *sink,
  604.   void *argument
  605. )
  606. {
  607.   SEC_ASN1EncoderContext *rv;
  608. #ifdef DEBUG
  609.   if( (void *)NULL == source ) {
  610.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  611.     return (nssASN1Encoder *)NULL;
  612.   }
  613.   if( (nssASN1Template *)NULL == template ) {
  614.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  615.     return (nssASN1Encoder *)NULL;
  616.   }
  617.   if( (nssASN1EncoderWriteFunction *)NULL == sink ) {
  618.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  619.     return (nssASN1Encoder *)NULL;
  620.   }
  621. #endif /* DEBUG */
  622.   switch( encoding ) {
  623.   case NSSASN1BER:
  624.   case NSSASN1DER:
  625.     break;
  626.   case NSSASN1CER:
  627.   case NSSASN1LWER:
  628.   case NSSASN1PER:
  629.   case NSSASN1UnknownEncoding:
  630.   default:
  631.     nss_SetError(NSS_ERROR_ENCODING_NOT_SUPPORTED);
  632.     return (nssASN1Encoder *)NULL;
  633.   }
  634.   rv = SEC_ASN1EncoderStart((void *)source, template, 
  635.                             (SEC_ASN1WriteProc)sink, argument);
  636.   if( (SEC_ASN1EncoderContext *)NULL == rv ) {
  637.     nss_SetError(PORT_GetError()); /* ugly */
  638.     return (nssASN1Encoder *)NULL;
  639.   }
  640.   if( NSSASN1DER == encoding ) {
  641.     sec_ASN1EncoderSetDER(rv);
  642.   }
  643. #ifdef DEBUG
  644.   if( PR_SUCCESS != encoder_add_pointer(rv) ) {
  645.     (void)SEC_ASN1EncoderFinish(rv);
  646.     return (nssASN1Encoder *)NULL;
  647.   }
  648. #endif /* DEBUG */
  649.   return (nssASN1Encoder *)rv;
  650. }
  651. /*
  652.  * nssASN1Encoder_Update
  653.  *
  654.  * The error may be one of the following values:
  655.  *  NSS_ERROR_INVALID_ASN1ENCODER
  656.  *  NSS_ERROR_INVALID_POINTER
  657.  *
  658.  * Return value:
  659.  *  PR_FAILURE upon error
  660.  *  PR_SUCCESS upon success
  661.  */
  662. NSS_IMPLEMENT PRStatus
  663. nssASN1Encoder_Update
  664. (
  665.   nssASN1Encoder *encoder,
  666.   const void *data,
  667.   PRUint32 length
  668. )
  669. {
  670.   PRStatus rv;
  671. #ifdef DEBUG
  672.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  673.     return PR_FAILURE;
  674.   }
  675.   /*
  676.    * Can data legitimately be NULL?  If not, verify..
  677.    */
  678. #endif /* DEBUG */
  679.   rv = SEC_ASN1EncoderUpdate((SEC_ASN1EncoderContext *)encoder,
  680.                              (const char *)data, 
  681.                              (unsigned long)length);
  682.   if( PR_SUCCESS != rv ) {
  683.     nss_SetError(PORT_GetError()); /* ugly */
  684.     return PR_FAILURE;
  685.   }
  686.   return PR_SUCCESS;
  687. }
  688. /*
  689.  * nssASN1Encoder_Finish
  690.  *
  691.  * Destructor.
  692.  *
  693.  * The error may be one of the following values:
  694.  *  NSS_ERROR_INVALID_ASN1ENCODER
  695.  *
  696.  * Return value:
  697.  *  PR_FAILURE upon error
  698.  *  PR_SUCCESS upon success
  699.  */
  700. NSS_IMPLEMENT PRStatus
  701. nssASN1Encoder_Finish
  702. (
  703.   nssASN1Encoder *encoder
  704. )
  705. {
  706.   PRStatus rv;
  707. #ifdef DEBUG
  708.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  709.     return PR_FAILURE;
  710.   }
  711. #endif /* DEBUG */
  712.   SEC_ASN1EncoderFinish((SEC_ASN1EncoderContext *)encoder);
  713.   rv = PR_SUCCESS; /* no error return defined for that call */
  714. #ifdef DEBUG
  715.   {
  716.     PRStatus rv2 = encoder_remove_pointer(encoder);
  717.     if( PR_SUCCESS == rv ) {
  718.       rv = rv2;
  719.     }
  720.   }
  721. #endif /* DEBUG */
  722.   return rv;
  723. }
  724. /*
  725.  * nssASN1Encoder_SetNotify
  726.  *
  727.  * This routine registers a callback notify routine with the encoder,
  728.  * which will be called whenever.. The specified argument will be
  729.  * passed as-is to the notify routine.  The routine pointer may be
  730.  * NULL, in which case no notify routine will be called.  This routine
  731.  * returns a PRStatus value; in the event of an error it will place
  732.  * an error on the error stack and return PR_FAILURE.
  733.  *
  734.  * The error may be one of the following values:
  735.  *  NSS_ERROR_INVALID_ASN1DECODER
  736.  *
  737.  * Return value:
  738.  *  PR_FAILURE upon error
  739.  *  PR_SUCCESS upon success
  740.  */
  741. NSS_IMPLEMENT PRStatus
  742. nssASN1Encoder_SetNotify
  743. (
  744.   nssASN1Encoder *encoder,
  745.   nssASN1NotifyFunction *callback,
  746.   void *argument
  747. )
  748. {
  749. #ifdef DEBUG
  750.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  751.     return PR_FAILURE;
  752.   }
  753. #endif /* DEBUG */
  754.   if( (nssASN1NotifyFunction *)NULL == callback ) {
  755.     SEC_ASN1EncoderClearNotifyProc((SEC_ASN1EncoderContext *)encoder);
  756.   } else {
  757.     SEC_ASN1EncoderSetNotifyProc((SEC_ASN1EncoderContext *)encoder,
  758.                                  (SEC_ASN1NotifyProc)callback,
  759.                                  argument);
  760.   }
  761.   /* no error return defined for those routines */
  762.   return PR_SUCCESS;
  763. }
  764. /*
  765.  * nssASN1Encoder_GetNotify
  766.  *
  767.  * If the optional pCallbackOpt argument to this routine is non-null,
  768.  * then the pointer to any callback function established for this
  769.  * decoder with nssASN1Encoder_SetNotify will be stored at the 
  770.  * location indicated by it.  If the optional pArgumentOpt pointer is
  771.  * non-null, the filter's closure argument will be stored there.
  772.  * This routine returns a PRStatus value; in the event of an error it
  773.  * will place an error on the error stack and return PR_FAILURE.
  774.  *
  775.  * The error may be one of the following values:
  776.  *  NSS_ERROR_INVALID_ASN1ENCODER
  777.  *
  778.  * Return value:
  779.  *  PR_FAILURE upon error
  780.  *  PR_SUCCESS upon success
  781.  */
  782. NSS_IMPLEMENT PRStatus
  783. nssASN1Encoder_GetNotify
  784. (
  785.   nssASN1Encoder *encoder,
  786.   nssASN1NotifyFunction **pCallbackOpt,
  787.   void **pArgumentOpt
  788. )
  789. {
  790. #ifdef DEBUG
  791.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  792.     return PR_FAILURE;
  793.   }
  794. #endif /* DEBUG */
  795.   if( (nssASN1NotifyFunction **)NULL != pCallbackOpt ) {
  796.     *pCallbackOpt = (nssASN1NotifyFunction *)NULL;
  797.   }
  798.   if( (void **)NULL != pArgumentOpt ) {
  799.     *pArgumentOpt = (void *)NULL;
  800.   }
  801.   /* Error because it's unimplemented */
  802.   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  803.   return PR_FAILURE;
  804. }
  805. /*
  806.  * nssASN1Encoder_SetStreaming
  807.  *
  808.  * 
  809.  * The error may be one of the following values:
  810.  *  NSS_ERROR_INVALID_ASN1ENCODER
  811.  *
  812.  * Return value:
  813.  *  PR_FAILURE upon error
  814.  *  PR_SUCCESS upon success
  815.  */
  816. NSS_IMPLEMENT PRStatus
  817. nssASN1Encoder_SetStreaming
  818. (
  819.   nssASN1Encoder *encoder,
  820.   PRBool streaming
  821. )
  822. {
  823.   SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext *)encoder;
  824. #ifdef DEBUG
  825.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  826.     return PR_FAILURE;
  827.   }
  828. #endif /* DEBUG */
  829.   if( streaming ) {
  830.     SEC_ASN1EncoderSetStreaming(cx);
  831.   } else {
  832.     SEC_ASN1EncoderClearStreaming(cx);
  833.   }
  834.   /* no error return defined for those routines */
  835.   return PR_SUCCESS;
  836. }
  837. /*
  838.  * nssASN1Encoder_GetStreaming
  839.  *
  840.  *
  841.  * The error may be one of the following values:
  842.  *  NSS_ERROR_INVALID_ASN1ENCODER
  843.  *  NSS_ERROR_INVALID_POINTER
  844.  *
  845.  * Return value:
  846.  *  PR_FAILURE upon error
  847.  *  PR_SUCCESS upon success
  848.  */
  849. NSS_EXTERN PRStatus
  850. nssASN1Encoder_GetStreaming
  851. (
  852.   nssASN1Encoder *encoder,
  853.   PRBool *pStreaming
  854. )
  855. {
  856. #ifdef DEBUG
  857.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  858.     return PR_FAILURE;
  859.   }
  860. #endif /* DEBUG */
  861.   if( (PRBool *)NULL != pStreaming ) {
  862.     *pStreaming = PR_FALSE;
  863.   }
  864.   /* Error because it's unimplemented */
  865.   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  866.   return PR_FAILURE;
  867. }
  868. /*
  869.  * nssASN1Encoder_SetTakeFromBuffer
  870.  *
  871.  *
  872.  * The error may be one of the following values:
  873.  *  NSS_ERROR_INVALID_ASN1ENCODER
  874.  *
  875.  * Return value:
  876.  *  PR_FAILURE upon error
  877.  *  PR_SUCCESS upon success
  878.  */
  879. NSS_IMPLEMENT PRStatus
  880. nssASN1Encoder_SetTakeFromBuffer
  881. (
  882.   nssASN1Encoder *encoder,
  883.   PRBool takeFromBuffer
  884. )
  885. {
  886.   SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext *)encoder;
  887. #ifdef DEBUG
  888.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  889.     return PR_FAILURE;
  890.   }
  891. #endif /* DEBUG */
  892.   if( takeFromBuffer ) {
  893.     SEC_ASN1EncoderSetTakeFromBuf(cx);
  894.   } else {
  895.     SEC_ASN1EncoderClearTakeFromBuf(cx);
  896.   }
  897.   /* no error return defined for those routines */
  898.   return PR_SUCCESS;
  899. }
  900. /*
  901.  * nssASN1Encoder_GetTakeFromBuffer
  902.  *
  903.  *
  904.  * The error may be one of the following values:
  905.  *  NSS_ERROR_INVALID_ASN1ENCODER
  906.  *  NSS_ERROR_INVALID_POINTER
  907.  *
  908.  * Return value:
  909.  *  PR_FAILURE upon error
  910.  *  PR_SUCCESS upon success
  911.  */
  912. NSS_IMPLEMENT PRStatus
  913. nssASN1Encoder_GetTakeFromBuffer
  914. (
  915.   nssASN1Encoder *encoder,
  916.   PRBool *pTakeFromBuffer
  917. )
  918. {
  919. #ifdef DEBUG
  920.   if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
  921.     return PR_FAILURE;
  922.   }
  923. #endif /* DEBUG */
  924.   if( (PRBool *)NULL != pTakeFromBuffer ) {
  925.     *pTakeFromBuffer = PR_FALSE;
  926.   }
  927.   /* Error because it's unimplemented */
  928.   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  929.   return PR_FAILURE;
  930. }
  931. /*
  932.  * nssASN1_Encode
  933.  *
  934.  * 
  935.  * The error may be one of the following values:
  936.  *  NSS_ERROR_NO_MEMORY
  937.  *  NSS_ERROR_INVALID_ARENA
  938.  *  NSS_ERROR_INVALID_POINTER
  939.  *  NSS_ERROR_ENCODING_NOT_SUPPORTED
  940.  *  ...
  941.  *
  942.  * Return value:
  943.  *  PR_FAILURE upon error
  944.  *  PR_SUCCESS upon success
  945.  */
  946. NSS_IMPLEMENT PRStatus
  947. nssASN1_Encode
  948. (
  949.   const void *source,
  950.   const nssASN1Template template[],
  951.   NSSASN1EncodingType encoding,
  952.   nssASN1EncoderWriteFunction *sink,
  953.   void *argument
  954. )
  955. {
  956.   PRStatus rv;
  957.   nssASN1Encoder *encoder;
  958.   encoder = nssASN1Encoder_Create(source, template, encoding, sink, argument);
  959.   if( (nssASN1Encoder *)NULL == encoder ) {
  960.     return PR_FAILURE;
  961.   }
  962.   rv = nssASN1Encoder_Update(encoder, (const void *)NULL, 0);
  963.   if( PR_SUCCESS != nssASN1Encoder_Finish(encoder) ) {
  964.     rv = PR_FAILURE;
  965.   }
  966.   return rv;
  967. }
  968. /*
  969.  * nssasn1_encode_item_count
  970.  *
  971.  * This is a helper function for nssASN1_EncodeItem.  It just counts
  972.  * up the space required for an encoding.
  973.  */
  974. static void
  975. nssasn1_encode_item_count
  976. (
  977.   void *arg,
  978.   const char *buf,
  979.   unsigned long len,
  980.   int depth,
  981.   nssASN1EncodingPart data_kind
  982. )
  983. {
  984.   unsigned long *count;
  985.   count = (unsigned long*)arg;
  986.   PR_ASSERT (count != NULL);
  987.   *count += len;
  988. }
  989. /*
  990.  * nssasn1_encode_item_store
  991.  *
  992.  * This is a helper function for nssASN1_EncodeItem.  It appends the
  993.  * new data onto the destination item.
  994.  */
  995. static void
  996. nssasn1_encode_item_store
  997. (
  998.   void *arg,
  999.   const char *buf,
  1000.   unsigned long len,
  1001.   int depth,
  1002.   nssASN1EncodingPart data_kind
  1003. )
  1004. {
  1005.   NSSItem *dest;
  1006.   dest = (NSSItem*)arg;
  1007.   PR_ASSERT (dest != NULL);
  1008.   memcpy((unsigned char *)dest->data + dest->size, buf, len);
  1009.   dest->size += len;
  1010. }
  1011. /*
  1012.  * nssASN1_EncodeItem
  1013.  *
  1014.  * There must be a better name.  If the optional arena argument is
  1015.  * non-null, it'll be used for the space.  If the optional rvOpt is
  1016.  * non-null, it'll be the return value-- if it is null, a new one
  1017.  * will be allocated.
  1018.  *
  1019.  * The error may be one of the following values:
  1020.  *  NSS_ERROR_NO_MEMORY
  1021.  *  NSS_ERROR_INVALID_ARENA
  1022.  *  NSS_ERROR_INVALID_POINTER
  1023.  *  NSS_ERROR_ENCODING_NOT_SUPPORTED
  1024.  *
  1025.  * Return value:
  1026.  *  NULL upon error
  1027.  *  A valid pointer to an NSSDER upon success
  1028.  */
  1029. NSS_IMPLEMENT NSSDER *
  1030. nssASN1_EncodeItem
  1031. (
  1032.   NSSArena *arenaOpt,
  1033.   NSSDER *rvOpt,
  1034.   const void *source,
  1035.   const nssASN1Template template[],
  1036.   NSSASN1EncodingType encoding
  1037. )
  1038. {
  1039.   PLArenaPool *hack = (PLArenaPool *)arenaOpt;
  1040.   NSSDER *rv;
  1041.   PRUint32 len = 0;
  1042.   PRStatus status;
  1043. #ifdef DEBUG
  1044.   if( (NSSArena *)NULL != arenaOpt ) {
  1045.     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
  1046.       return (NSSDER *)NULL;
  1047.     }
  1048.   }
  1049.   if( (void *)NULL == source ) {
  1050.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  1051.     return (NSSDER *)NULL;
  1052.   }
  1053.   if( (nssASN1Template *)NULL == template ) {
  1054.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  1055.     return (NSSDER *)NULL;
  1056.   }
  1057. #endif /* DEBUG */
  1058.   status = nssASN1_Encode(source, template, encoding, 
  1059.                           (nssASN1EncoderWriteFunction *)nssasn1_encode_item_count, 
  1060.                           &len);
  1061.   if( PR_SUCCESS != status ) {
  1062.     return (NSSDER *)NULL;
  1063.   }
  1064.   if( (NSSDER *)NULL == rvOpt ) {
  1065.     rv = nss_ZNEW(arenaOpt, NSSDER);
  1066.     if( (NSSDER *)NULL == rv ) {
  1067.       return (NSSDER *)NULL;
  1068.     }
  1069.   } else {
  1070.     rv = rvOpt;
  1071.   }
  1072.   rv->size = len;
  1073.   rv->data = nss_ZAlloc(arenaOpt, len);
  1074.   if( (void *)NULL == rv->data ) {
  1075.     if( (NSSDER *)NULL == rvOpt ) {
  1076.       nss_ZFreeIf(rv);
  1077.     }
  1078.     return (NSSDER *)NULL;
  1079.   }
  1080.   rv->size = 0; /* for nssasn1_encode_item_store */
  1081.   status = nssASN1_Encode(source, template, encoding,
  1082.                           (nssASN1EncoderWriteFunction *)nssasn1_encode_item_store, 
  1083.                           rv);
  1084.   if( PR_SUCCESS != status ) {
  1085.     nss_ZFreeIf(rv->data);
  1086.     if( (NSSDER *)NULL == rvOpt ) {
  1087.       nss_ZFreeIf(rv);
  1088.     }
  1089.     return (NSSDER *)NULL;
  1090.   }
  1091.   PR_ASSERT(rv->size == len);
  1092.   return rv;
  1093. }
  1094. /*
  1095.  * nssASN1_CreatePRUint32FromBER
  1096.  *
  1097.  */
  1098. NSS_IMPLEMENT PRStatus
  1099. nssASN1_CreatePRUint32FromBER
  1100. (
  1101.   NSSBER *encoded,
  1102.   PRUint32 *pResult
  1103. )
  1104. {
  1105.   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  1106.   return PR_FALSE;
  1107. }
  1108. /*
  1109.  * nssASN1_GetDERFromPRUint32
  1110.  *
  1111.  */
  1112. NSS_EXTERN NSSDER *
  1113. nssASN1_GetDERFromPRUint32
  1114. (
  1115.   NSSArena *arenaOpt,
  1116.   NSSDER *rvOpt,
  1117.   PRUint32 value
  1118. )
  1119. {
  1120.   NSSDER *rv;
  1121.   PLArenaPool *hack = (PLArenaPool *)arenaOpt;
  1122.   SECItem *item;
  1123. #ifdef DEBUG
  1124.   if( (NSSArena *)NULL != arenaOpt ) {
  1125.     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
  1126.       return (NSSDER *)NULL;
  1127.     }
  1128.   }
  1129. #endif /* DEBUG */
  1130.   if( (NSSDER *)NULL == rvOpt ) {
  1131.     rv = nss_ZNEW(arenaOpt, NSSDER);
  1132.     if( (NSSDER *)NULL == rv ) {
  1133.       return (NSSDER *)NULL;
  1134.     }
  1135.   } else {
  1136.     rv = rvOpt;
  1137.   }
  1138.   item = SEC_ASN1EncodeUnsignedInteger(hack, (SECItem *)rv, value);
  1139.   if( (SECItem *)NULL == item ) {
  1140.     if( (NSSDER *)NULL == rvOpt ) {
  1141.       (void)nss_ZFreeIf(rv);
  1142.     }
  1143.     nss_SetError(PORT_GetError()); /* ugly */
  1144.     return (NSSDER *)NULL;
  1145.   }
  1146.   /* 
  1147.    * I happen to know that these things look alike.. but I'm only
  1148.    * doing it for these "temporary" wrappers.  This is an evil thing.
  1149.    */
  1150.   return (NSSDER *)item;
  1151. }
  1152. /*himom*/
  1153. NSS_IMPLEMENT PRStatus
  1154. nssASN1_CreatePRInt32FromBER
  1155. (
  1156.   NSSBER *encoded,
  1157.   PRInt32 *pResult
  1158. )
  1159. {
  1160.   nss_SetError(NSS_ERROR_INTERNAL_ERROR);
  1161.   return PR_FALSE;
  1162. }
  1163. /*
  1164.  * nssASN1_GetDERFromPRInt32
  1165.  *
  1166.  */
  1167. NSS_IMPLEMENT NSSDER *
  1168. nssASN1_GetDERFromPRInt32
  1169. (
  1170.   NSSArena *arenaOpt,
  1171.   NSSDER *rvOpt,
  1172.   PRInt32 value
  1173. )
  1174. {
  1175.   NSSDER *rv;
  1176.   PLArenaPool *hack = (PLArenaPool *)arenaOpt;
  1177.   SECItem *item;
  1178. #ifdef DEBUG
  1179.   if( (NSSArena *)NULL != arenaOpt ) {
  1180.     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
  1181.       return (NSSDER *)NULL;
  1182.     }
  1183.   }
  1184. #endif /* DEBUG */
  1185.   if( (NSSDER *)NULL == rvOpt ) {
  1186.     rv = nss_ZNEW(arenaOpt, NSSDER);
  1187.     if( (NSSDER *)NULL == rv ) {
  1188.       return (NSSDER *)NULL;
  1189.     }
  1190.   } else {
  1191.     rv = rvOpt;
  1192.   }
  1193.   item = SEC_ASN1EncodeInteger(hack, (SECItem *)rv, value);
  1194.   if( (SECItem *)NULL == item ) {
  1195.     if( (NSSDER *)NULL == rvOpt ) {
  1196.       (void)nss_ZFreeIf(rv);
  1197.     }
  1198.     nss_SetError(PORT_GetError()); /* ugly */
  1199.     return (NSSDER *)NULL;
  1200.   }
  1201.   /* 
  1202.    * I happen to know that these things look alike.. but I'm only
  1203.    * doing it for these "temporary" wrappers.  This is an evil thing.
  1204.    */
  1205.   return (NSSDER *)item;
  1206. }
  1207. /*
  1208.  * Generic Templates
  1209.  * One for each of the simple types, plus a special one for ANY, plus:
  1210.  * - a pointer to each one of those
  1211.  * - a set of each one of those
  1212.  *
  1213.  * Note that these are alphabetical (case insensitive); please add new
  1214.  * ones in the appropriate place.
  1215.  */
  1216. const nssASN1Template *nssASN1Template_Any =                             (nssASN1Template *)SEC_AnyTemplate;
  1217. const nssASN1Template *nssASN1Template_BitString =                       (nssASN1Template *)SEC_BitStringTemplate;
  1218. const nssASN1Template *nssASN1Template_BMPString =                       (nssASN1Template *)SEC_BMPStringTemplate;
  1219. const nssASN1Template *nssASN1Template_Boolean =                         (nssASN1Template *)SEC_BooleanTemplate;
  1220. const nssASN1Template *nssASN1Template_Enumerated =                      (nssASN1Template *)SEC_EnumeratedTemplate;
  1221. const nssASN1Template *nssASN1Template_GeneralizedTime =                 (nssASN1Template *)SEC_GeneralizedTimeTemplate;
  1222. const nssASN1Template *nssASN1Template_IA5String =                       (nssASN1Template *)SEC_IA5StringTemplate;
  1223. const nssASN1Template *nssASN1Template_Integer =                         (nssASN1Template *)SEC_IntegerTemplate;
  1224. const nssASN1Template *nssASN1Template_Null =                            (nssASN1Template *)SEC_NullTemplate;
  1225. const nssASN1Template *nssASN1Template_ObjectID =                        (nssASN1Template *)SEC_ObjectIDTemplate;
  1226. const nssASN1Template *nssASN1Template_OctetString =                     (nssASN1Template *)SEC_OctetStringTemplate;
  1227. const nssASN1Template *nssASN1Template_PrintableString =                 (nssASN1Template *)SEC_PrintableStringTemplate;
  1228. const nssASN1Template *nssASN1Template_T61String =                       (nssASN1Template *)SEC_T61StringTemplate;
  1229. const nssASN1Template *nssASN1Template_UniversalString =                 (nssASN1Template *)SEC_UniversalStringTemplate;
  1230. const nssASN1Template *nssASN1Template_UTCTime =                         (nssASN1Template *)SEC_UTCTimeTemplate;
  1231. const nssASN1Template *nssASN1Template_UTF8String =                      (nssASN1Template *)SEC_UTF8StringTemplate;
  1232. const nssASN1Template *nssASN1Template_VisibleString =                   (nssASN1Template *)SEC_VisibleStringTemplate;
  1233. const nssASN1Template *nssASN1Template_PointerToAny =                    (nssASN1Template *)SEC_PointerToAnyTemplate;
  1234. const nssASN1Template *nssASN1Template_PointerToBitString =              (nssASN1Template *)SEC_PointerToBitStringTemplate;
  1235. const nssASN1Template *nssASN1Template_PointerToBMPString =              (nssASN1Template *)SEC_PointerToBMPStringTemplate;
  1236. const nssASN1Template *nssASN1Template_PointerToBoolean =                (nssASN1Template *)SEC_PointerToBooleanTemplate;
  1237. const nssASN1Template *nssASN1Template_PointerToEnumerated =             (nssASN1Template *)SEC_PointerToEnumeratedTemplate;
  1238. const nssASN1Template *nssASN1Template_PointerToGeneralizedTime =        (nssASN1Template *)SEC_PointerToGeneralizedTimeTemplate;
  1239. const nssASN1Template *nssASN1Template_PointerToIA5String =              (nssASN1Template *)SEC_PointerToIA5StringTemplate;
  1240. const nssASN1Template *nssASN1Template_PointerToInteger =                (nssASN1Template *)SEC_PointerToIntegerTemplate;
  1241. const nssASN1Template *nssASN1Template_PointerToNull =                   (nssASN1Template *)SEC_PointerToNullTemplate;
  1242. const nssASN1Template *nssASN1Template_PointerToObjectID =               (nssASN1Template *)SEC_PointerToObjectIDTemplate;
  1243. const nssASN1Template *nssASN1Template_PointerToOctetString =            (nssASN1Template *)SEC_PointerToOctetStringTemplate;
  1244. const nssASN1Template *nssASN1Template_PointerToPrintableString =        (nssASN1Template *)SEC_PointerToPrintableStringTemplate;
  1245. const nssASN1Template *nssASN1Template_PointerToT61String =              (nssASN1Template *)SEC_PointerToT61StringTemplate;
  1246. const nssASN1Template *nssASN1Template_PointerToUniversalString =        (nssASN1Template *)SEC_PointerToUniversalStringTemplate;
  1247. const nssASN1Template *nssASN1Template_PointerToUTCTime =                (nssASN1Template *)SEC_PointerToUTCTimeTemplate;
  1248. const nssASN1Template *nssASN1Template_PointerToUTF8String =             (nssASN1Template *)SEC_PointerToUTF8StringTemplate;
  1249. const nssASN1Template *nssASN1Template_PointerToVisibleString =          (nssASN1Template *)SEC_PointerToVisibleStringTemplate;
  1250. const nssASN1Template *nssASN1Template_SetOfAny =                        (nssASN1Template *)SEC_SetOfAnyTemplate;
  1251. const nssASN1Template *nssASN1Template_SetOfBitString =                  (nssASN1Template *)SEC_SetOfBitStringTemplate;
  1252. const nssASN1Template *nssASN1Template_SetOfBMPString =                  (nssASN1Template *)SEC_SetOfBMPStringTemplate;
  1253. const nssASN1Template *nssASN1Template_SetOfBoolean =                    (nssASN1Template *)SEC_SetOfBooleanTemplate;
  1254. const nssASN1Template *nssASN1Template_SetOfEnumerated =                 (nssASN1Template *)SEC_SetOfEnumeratedTemplate;
  1255. const nssASN1Template *nssASN1Template_SetOfGeneralizedTime =            (nssASN1Template *)SEC_SetOfGeneralizedTimeTemplate;
  1256. const nssASN1Template *nssASN1Template_SetOfIA5String =                  (nssASN1Template *)SEC_SetOfIA5StringTemplate;
  1257. const nssASN1Template *nssASN1Template_SetOfInteger =                    (nssASN1Template *)SEC_SetOfIntegerTemplate;
  1258. const nssASN1Template *nssASN1Template_SetOfNull =                       (nssASN1Template *)SEC_SetOfNullTemplate;
  1259. const nssASN1Template *nssASN1Template_SetOfObjectID =                   (nssASN1Template *)SEC_SetOfObjectIDTemplate;
  1260. const nssASN1Template *nssASN1Template_SetOfOctetString =                (nssASN1Template *)SEC_SetOfOctetStringTemplate;
  1261. const nssASN1Template *nssASN1Template_SetOfPrintableString =            (nssASN1Template *)SEC_SetOfPrintableStringTemplate;
  1262. const nssASN1Template *nssASN1Template_SetOfT61String =                  (nssASN1Template *)SEC_SetOfT61StringTemplate;
  1263. const nssASN1Template *nssASN1Template_SetOfUniversalString =            (nssASN1Template *)SEC_SetOfUniversalStringTemplate;
  1264. const nssASN1Template *nssASN1Template_SetOfUTCTime =                    (nssASN1Template *)SEC_SetOfUTCTimeTemplate;
  1265. const nssASN1Template *nssASN1Template_SetOfUTF8String =                 (nssASN1Template *)SEC_SetOfUTF8StringTemplate;
  1266. const nssASN1Template *nssASN1Template_SetOfVisibleString =              (nssASN1Template *)SEC_SetOfVisibleStringTemplate;
  1267. /*
  1268.  *
  1269.  */
  1270. NSS_IMPLEMENT NSSUTF8 *
  1271. nssUTF8_CreateFromBER
  1272. (
  1273.   NSSArena *arenaOpt,
  1274.   nssStringType type,
  1275.   NSSBER *berData
  1276. )
  1277. {
  1278.   NSSUTF8 *rv = NULL;
  1279.   PRUint8 tag;
  1280.   NSSArena *a;
  1281.   NSSItem in;
  1282.   NSSItem out;
  1283.   PRStatus st;
  1284.   const nssASN1Template *templ;
  1285. #ifdef NSSDEBUG
  1286.   if( (NSSArena *)NULL != arenaOpt ) {
  1287.     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
  1288.       return (NSSUTF8 *)NULL;
  1289.     }
  1290.   }
  1291.   if( (NSSBER *)NULL == berData ) {
  1292.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  1293.     return (NSSUTF8 *)NULL;
  1294.   }
  1295.   if( (void *)NULL == berData->data ) {
  1296.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  1297.     return (NSSUTF8 *)NULL;
  1298.   }
  1299. #endif /* NSSDEBUG */
  1300.   a = NSSArena_Create();
  1301.   if( (NSSArena *)NULL == a ) {
  1302.     return (NSSUTF8 *)NULL;
  1303.   }
  1304.   in = *berData;
  1305.   /*
  1306.    * By the way, at first I succumbed to the temptation to make
  1307.    * this an incestuous nested switch statement.  Count yourself
  1308.    * lucky I cleaned it up.
  1309.    */
  1310.   switch( type ) {
  1311.   case nssStringType_DirectoryString:
  1312.     /*
  1313.      * draft-ietf-pkix-ipki-part1-11 says in part:
  1314.      *
  1315.      * DirectoryString { INTEGER:maxSize } ::= CHOICE {
  1316.      *   teletexString           TeletexString (SIZE (1..maxSize)),
  1317.      *   printableString         PrintableString (SIZE (1..maxSize)),
  1318.      *   universalString         UniversalString (SIZE (1..maxSize)),
  1319.      *   bmpString               BMPString (SIZE(1..maxSize)),
  1320.      *   utf8String              UTF8String (SIZE(1..maxSize))
  1321.      *                       }
  1322.      *
  1323.      * The tags are:
  1324.      *  TeletexString       UNIVERSAL 20
  1325.      *  PrintableString     UNIVERSAL 19
  1326.      *  UniversalString     UNIVERSAL 28
  1327.      *  BMPString           UNIVERSAL 30
  1328.      *  UTF8String          UNIVERSAL 12
  1329.      *
  1330.      * "UNIVERSAL" tags have bits 8 and 7 zero, bit 6 is zero for
  1331.      * primitive encodings, and if the tag value is less than 30,
  1332.      * the tag value is directly encoded in bits 5 through 1.
  1333.      */
  1334.     in.data = (void *)&(((PRUint8 *)berData->data)[1]);
  1335.     in.size = berData->size-1;
  1336.     
  1337.     tag = *(PRUint8 *)berData->data;
  1338.     switch( tag & nssASN1_TAGNUM_MASK ) {
  1339.     case 20:
  1340.       /*
  1341.        * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
  1342.        * below) but is T61 a suitable value for "Latin-1"?
  1343.        */
  1344.       templ = nssASN1Template_T61String;
  1345.       type = nssStringType_TeletexString;
  1346.       break;
  1347.     case 19:
  1348.       templ = nssASN1Template_PrintableString;
  1349.       type = nssStringType_PrintableString;
  1350.       break;
  1351.     case 28:
  1352.       templ = nssASN1Template_UniversalString;
  1353.       type = nssStringType_UniversalString;
  1354.       break;
  1355.     case 30:
  1356.       templ = nssASN1Template_BMPString;
  1357.       type = nssStringType_BMPString;
  1358.       break;
  1359.     case 12:
  1360.       templ = nssASN1Template_UTF8String;
  1361.       type = nssStringType_UTF8String;
  1362.       break;
  1363.     default:
  1364.       nss_SetError(NSS_ERROR_INVALID_POINTER); /* "pointer"? */
  1365.       (void)NSSArena_Destroy(a);
  1366.       return (NSSUTF8 *)NULL;
  1367.     }
  1368.     break;
  1369.   case nssStringType_TeletexString:
  1370.     /*
  1371.      * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
  1372.      * below) but is T61 a suitable value for "Latin-1"?
  1373.      */
  1374.     templ = nssASN1Template_T61String;
  1375.     break;
  1376.    
  1377.   case nssStringType_PrintableString:
  1378.     templ = nssASN1Template_PrintableString;
  1379.     break;
  1380.   case nssStringType_UniversalString:
  1381.     templ = nssASN1Template_UniversalString;
  1382.     break;
  1383.   case nssStringType_BMPString:
  1384.     templ = nssASN1Template_BMPString;
  1385.     break;
  1386.   case nssStringType_UTF8String:
  1387.     templ = nssASN1Template_UTF8String;
  1388.     break;
  1389.   case nssStringType_PHGString:
  1390.     templ = nssASN1Template_IA5String;
  1391.     break;
  1392.   default:
  1393.     nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
  1394.     (void)NSSArena_Destroy(a);
  1395.     return (NSSUTF8 *)NULL;
  1396.   }
  1397.     
  1398.   st = nssASN1_DecodeBER(a, &out, templ, &in);
  1399.   
  1400.   if( PR_SUCCESS == st ) {
  1401.     rv = nssUTF8_Create(arenaOpt, type, out.data, out.size);
  1402.   }
  1403.   (void)NSSArena_Destroy(a);
  1404.   
  1405.   return rv;
  1406. }
  1407. NSS_EXTERN NSSDER *
  1408. nssUTF8_GetDEREncoding
  1409. (
  1410.   NSSArena *arenaOpt,
  1411.   nssStringType type,
  1412.   const NSSUTF8 *string
  1413. )
  1414. {
  1415.   NSSDER *rv = (NSSDER *)NULL;
  1416.   NSSItem str;
  1417.   NSSDER *der;
  1418.   const nssASN1Template *templ;
  1419.   NSSArena *a;
  1420. #ifdef NSSDEBUG
  1421.   if( (NSSArena *)NULL != arenaOpt ) {
  1422.     if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
  1423.       return (NSSDER *)NULL;
  1424.     }
  1425.   }
  1426.   if( (const NSSUTF8 *)NULL == string ) {
  1427.     nss_SetError(NSS_ERROR_INVALID_POINTER);
  1428.     return (NSSDER *)NULL;
  1429.   }
  1430. #endif /* NSSDEBUG */
  1431.   str.data = (void *)string;
  1432.   str.size = nssUTF8_Size(string, (PRStatus *)NULL);
  1433.   if( 0 == str.size ) {
  1434.     return (NSSDER *)NULL;
  1435.   }
  1436.   a = NSSArena_Create();
  1437.   if( (NSSArena *)NULL == a ) {
  1438.     return (NSSDER *)NULL;
  1439.   }
  1440.   switch( type ) {
  1441.   case nssStringType_DirectoryString:
  1442.     {
  1443.       NSSDER *utf;
  1444.       PRUint8 *c;
  1445.       utf = nssASN1_EncodeItem(a, (NSSDER *)NULL, &str, 
  1446.                                nssASN1Template_UTF8String,
  1447.                                NSSASN1DER);
  1448.       if( (NSSDER *)NULL == utf ) {
  1449.         (void)NSSArena_Destroy(a);
  1450.         return (NSSDER *)NULL;
  1451.       }
  1452.       rv = nss_ZNEW(arenaOpt, NSSDER);
  1453.       if( (NSSDER *)NULL == rv ) {
  1454.         (void)NSSArena_Destroy(a);
  1455.         return (NSSDER *)NULL;
  1456.       }
  1457.       rv->size = utf->size + 1;
  1458.       rv->data = nss_ZAlloc(arenaOpt, rv->size);
  1459.       if( (void *)NULL == rv->data ) {
  1460.         (void)nss_ZFreeIf(rv);
  1461.         (void)NSSArena_Destroy(a);
  1462.         return (NSSDER *)NULL;
  1463.       }
  1464.       
  1465.       c = (PRUint8 *)rv->data;
  1466.       (void)nsslibc_memcpy(&c[1], utf->data, utf->size);
  1467.       *c = 12; /* UNIVERSAL primitive encoding tag for UTF8String */
  1468.       (void)NSSArena_Destroy(a);
  1469.       return rv;
  1470.     }
  1471.   case nssStringType_TeletexString:
  1472.     /*
  1473.      * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
  1474.      * below) but is T61 a suitable value for "Latin-1"?
  1475.      */
  1476.     templ = nssASN1Template_T61String;
  1477.     break;
  1478.   case nssStringType_PrintableString:
  1479.     templ = nssASN1Template_PrintableString;
  1480.     break;
  1481.   case nssStringType_UniversalString:
  1482.     templ = nssASN1Template_UniversalString;
  1483.     break;
  1484.   case nssStringType_BMPString:
  1485.     templ = nssASN1Template_BMPString;
  1486.     break;
  1487.   case nssStringType_UTF8String:
  1488.     templ = nssASN1Template_UTF8String;
  1489.     break;
  1490.   case nssStringType_PHGString:
  1491.     templ = nssASN1Template_IA5String;
  1492.     break;
  1493.   default:
  1494.     nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
  1495.     (void)NSSArena_Destroy(a);
  1496.     return (NSSDER *)NULL;
  1497.   }
  1498.   der = nssUTF8_GetDEREncoding(a, type, string);
  1499.   if( (NSSItem *)NULL == der ) {
  1500.     (void)NSSArena_Destroy(a);
  1501.     return (NSSDER *)NULL;
  1502.   }
  1503.   rv = nssASN1_EncodeItem(arenaOpt, (NSSDER *)NULL, der, templ, NSSASN1DER);
  1504.   if( (NSSDER *)NULL == rv ) {
  1505.     (void)NSSArena_Destroy(a);
  1506.     return (NSSDER *)NULL;
  1507.   }
  1508.   (void)NSSArena_Destroy(a);
  1509.   return rv;
  1510. }