~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/asn1/asn1.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

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