Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / security / nss / lib / smime / cmscipher.c
blob374e0bbd0fe994162b5a186a8fd22a3c1b0eaf89
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * Encryption/decryption routines for CMS implementation, none of which are exported.
40 * $Id: cmscipher.c,v 1.12 2008/02/03 06:08:49 nelson%bolyard.com Exp $
43 #include "cmslocal.h"
45 #include "secoid.h"
46 #include "secitem.h"
47 #include "pk11func.h"
48 #include "secerr.h"
49 #include "secpkcs5.h"
52 * -------------------------------------------------------------------
53 * Cipher stuff.
56 typedef SECStatus (*nss_cms_cipher_function) (void *, unsigned char *, unsigned int *,
57 unsigned int, const unsigned char *, unsigned int);
58 typedef SECStatus (*nss_cms_cipher_destroy) (void *, PRBool);
60 #define BLOCK_SIZE 4096
62 struct NSSCMSCipherContextStr {
63 void * cx; /* PK11 cipher context */
64 nss_cms_cipher_function doit;
65 nss_cms_cipher_destroy destroy;
66 PRBool encrypt; /* encrypt / decrypt switch */
67 int block_size; /* block & pad sizes for cipher */
68 int pad_size;
69 int pending_count; /* pending data (not yet en/decrypted */
70 unsigned char pending_buf[BLOCK_SIZE];/* because of blocking */
74 * NSS_CMSCipherContext_StartDecrypt - create a cipher context to do decryption
75 * based on the given bulk encryption key and algorithm identifier (which
76 * may include an iv).
78 * XXX Once both are working, it might be nice to combine this and the
79 * function below (for starting up encryption) into one routine, and just
80 * have two simple cover functions which call it.
82 NSSCMSCipherContext *
83 NSS_CMSCipherContext_StartDecrypt(PK11SymKey *key, SECAlgorithmID *algid)
85 NSSCMSCipherContext *cc;
86 void *ciphercx;
87 CK_MECHANISM_TYPE cryptoMechType;
88 SECItem *param;
89 PK11SlotInfo *slot;
90 SECOidTag algtag;
92 algtag = SECOID_GetAlgorithmTag(algid);
94 /* set param and mechanism */
95 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
96 SECItem *pwitem;
98 pwitem = PK11_GetSymKeyUserData(key);
99 if (!pwitem)
100 return NULL;
102 cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
103 if (cryptoMechType == CKM_INVALID_MECHANISM) {
104 return NULL;
107 } else {
108 cryptoMechType = PK11_AlgtagToMechanism(algtag);
109 if ((param = PK11_ParamFromAlgid(algid)) == NULL)
110 return NULL;
113 cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
114 if (cc == NULL) {
115 SECITEM_FreeItem(param,PR_TRUE);
116 return NULL;
119 /* figure out pad and block sizes */
120 cc->pad_size = PK11_GetBlockSize(cryptoMechType, param);
121 slot = PK11_GetSlotFromKey(key);
122 cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
123 PK11_FreeSlot(slot);
125 /* create PK11 cipher context */
126 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
127 key, param);
128 SECITEM_FreeItem(param, PR_TRUE);
129 if (ciphercx == NULL) {
130 PORT_Free (cc);
131 return NULL;
134 cc->cx = ciphercx;
135 cc->doit = (nss_cms_cipher_function) PK11_CipherOp;
136 cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext;
137 cc->encrypt = PR_FALSE;
138 cc->pending_count = 0;
140 return cc;
144 * NSS_CMSCipherContext_StartEncrypt - create a cipher object to do encryption,
145 * based on the given bulk encryption key and algorithm tag. Fill in the
146 * algorithm identifier (which may include an iv) appropriately.
148 * XXX Once both are working, it might be nice to combine this and the
149 * function above (for starting up decryption) into one routine, and just
150 * have two simple cover functions which call it.
152 NSSCMSCipherContext *
153 NSS_CMSCipherContext_StartEncrypt(PRArenaPool *poolp, PK11SymKey *key, SECAlgorithmID *algid)
155 NSSCMSCipherContext *cc;
156 void *ciphercx;
157 SECItem *param;
158 SECStatus rv;
159 CK_MECHANISM_TYPE cryptoMechType;
160 PK11SlotInfo *slot;
161 PRBool needToEncodeAlgid = PR_FALSE;
162 SECOidTag algtag = SECOID_GetAlgorithmTag(algid);
164 /* set param and mechanism */
165 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
166 SECItem *pwitem;
168 pwitem = PK11_GetSymKeyUserData(key);
169 if (!pwitem)
170 return NULL;
172 cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
173 if (cryptoMechType == CKM_INVALID_MECHANISM) {
174 return NULL;
176 } else {
177 cryptoMechType = PK11_AlgtagToMechanism(algtag);
178 if ((param = PK11_GenerateNewParam(cryptoMechType, key)) == NULL)
179 return NULL;
180 needToEncodeAlgid = PR_TRUE;
183 cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext));
184 if (cc == NULL) {
185 goto loser;
188 /* now find pad and block sizes for our mechanism */
189 cc->pad_size = PK11_GetBlockSize(cryptoMechType, param);
190 slot = PK11_GetSlotFromKey(key);
191 cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
192 PK11_FreeSlot(slot);
194 /* and here we go, creating a PK11 cipher context */
195 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
196 key, param);
197 if (ciphercx == NULL) {
198 PORT_Free(cc);
199 cc = NULL;
200 goto loser;
204 * These are placed after the CreateContextBySymKey() because some
205 * mechanisms have to generate their IVs from their card (i.e. FORTEZZA).
206 * Don't move it from here.
207 * XXX is that right? the purpose of this is to get the correct algid
208 * containing the IVs etc. for encoding. this means we need to set this up
209 * BEFORE encoding the algid in the contentInfo, right?
211 if (needToEncodeAlgid) {
212 rv = PK11_ParamToAlgid(algtag, param, poolp, algid);
213 if(rv != SECSuccess) {
214 PORT_Free(cc);
215 cc = NULL;
216 goto loser;
220 cc->cx = ciphercx;
221 cc->doit = (nss_cms_cipher_function)PK11_CipherOp;
222 cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext;
223 cc->encrypt = PR_TRUE;
224 cc->pending_count = 0;
226 loser:
227 SECITEM_FreeItem(param, PR_TRUE);
229 return cc;
232 void
233 NSS_CMSCipherContext_Destroy(NSSCMSCipherContext *cc)
235 PORT_Assert(cc != NULL);
236 if (cc == NULL)
237 return;
238 (*cc->destroy)(cc->cx, PR_TRUE);
239 PORT_Free(cc);
243 * NSS_CMSCipherContext_DecryptLength - find the output length of the next call to decrypt.
245 * cc - the cipher context
246 * input_len - number of bytes used as input
247 * final - true if this is the final chunk of data
249 * Result can be used to perform memory allocations. Note that the amount
250 * is exactly accurate only when not doing a block cipher or when final
251 * is false, otherwise it is an upper bound on the amount because until
252 * we see the data we do not know how many padding bytes there are
253 * (always between 1 and bsize).
255 * Note that this can return zero, which does not mean that the decrypt
256 * operation can be skipped! (It simply means that there are not enough
257 * bytes to make up an entire block; the bytes will be reserved until
258 * there are enough to encrypt/decrypt at least one block.) However,
259 * if zero is returned it *does* mean that no output buffer need be
260 * passed in to the subsequent decrypt operation, as no output bytes
261 * will be stored.
263 unsigned int
264 NSS_CMSCipherContext_DecryptLength(NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
266 int blocks, block_size;
268 PORT_Assert (! cc->encrypt);
270 block_size = cc->block_size;
273 * If this is not a block cipher, then we always have the same
274 * number of output bytes as we had input bytes.
276 if (block_size == 0)
277 return input_len;
280 * On the final call, we will always use up all of the pending
281 * bytes plus all of the input bytes, *but*, there will be padding
282 * at the end and we cannot predict how many bytes of padding we
283 * will end up removing. The amount given here is actually known
284 * to be at least 1 byte too long (because we know we will have
285 * at least 1 byte of padding), but seemed clearer/better to me.
287 if (final)
288 return cc->pending_count + input_len;
291 * Okay, this amount is exactly what we will output on the
292 * next cipher operation. We will always hang onto the last
293 * 1 - block_size bytes for non-final operations. That is,
294 * we will do as many complete blocks as we can *except* the
295 * last block (complete or partial). (This is because until
296 * we know we are at the end, we cannot know when to interpret
297 * and removing the padding byte(s), which are guaranteed to
298 * be there.)
300 blocks = (cc->pending_count + input_len - 1) / block_size;
301 return blocks * block_size;
305 * NSS_CMSCipherContext_EncryptLength - find the output length of the next call to encrypt.
307 * cc - the cipher context
308 * input_len - number of bytes used as input
309 * final - true if this is the final chunk of data
311 * Result can be used to perform memory allocations.
313 * Note that this can return zero, which does not mean that the encrypt
314 * operation can be skipped! (It simply means that there are not enough
315 * bytes to make up an entire block; the bytes will be reserved until
316 * there are enough to encrypt/decrypt at least one block.) However,
317 * if zero is returned it *does* mean that no output buffer need be
318 * passed in to the subsequent encrypt operation, as no output bytes
319 * will be stored.
321 unsigned int
322 NSS_CMSCipherContext_EncryptLength(NSSCMSCipherContext *cc, unsigned int input_len, PRBool final)
324 int blocks, block_size;
325 int pad_size;
327 PORT_Assert (cc->encrypt);
329 block_size = cc->block_size;
330 pad_size = cc->pad_size;
333 * If this is not a block cipher, then we always have the same
334 * number of output bytes as we had input bytes.
336 if (block_size == 0)
337 return input_len;
340 * On the final call, we only send out what we need for
341 * remaining bytes plus the padding. (There is always padding,
342 * so even if we have an exact number of blocks as input, we
343 * will add another full block that is just padding.)
345 if (final) {
346 if (pad_size == 0) {
347 return cc->pending_count + input_len;
348 } else {
349 blocks = (cc->pending_count + input_len) / pad_size;
350 blocks++;
351 return blocks*pad_size;
356 * Now, count the number of complete blocks of data we have.
358 blocks = (cc->pending_count + input_len) / block_size;
361 return blocks * block_size;
366 * NSS_CMSCipherContext_Decrypt - do the decryption
368 * cc - the cipher context
369 * output - buffer for decrypted result bytes
370 * output_len_p - number of bytes in output
371 * max_output_len - upper bound on bytes to put into output
372 * input - pointer to input bytes
373 * input_len - number of input bytes
374 * final - true if this is the final chunk of data
376 * Decrypts a given length of input buffer (starting at "input" and
377 * containing "input_len" bytes), placing the decrypted bytes in
378 * "output" and storing the output length in "*output_len_p".
379 * "cc" is the return value from NSS_CMSCipher_StartDecrypt.
380 * When "final" is true, this is the last of the data to be decrypted.
382 * This is much more complicated than it sounds when the cipher is
383 * a block-type, meaning that the decryption function will only
384 * operate on whole blocks. But our caller is operating stream-wise,
385 * and can pass in any number of bytes. So we need to keep track
386 * of block boundaries. We save excess bytes between calls in "cc".
387 * We also need to determine which bytes are padding, and remove
388 * them from the output. We can only do this step when we know we
389 * have the final block of data. PKCS #7 specifies that the padding
390 * used for a block cipher is a string of bytes, each of whose value is
391 * the same as the length of the padding, and that all data is padded.
392 * (Even data that starts out with an exact multiple of blocks gets
393 * added to it another block, all of which is padding.)
395 SECStatus
396 NSS_CMSCipherContext_Decrypt(NSSCMSCipherContext *cc, unsigned char *output,
397 unsigned int *output_len_p, unsigned int max_output_len,
398 const unsigned char *input, unsigned int input_len,
399 PRBool final)
401 int blocks, bsize, pcount, padsize;
402 unsigned int max_needed, ifraglen, ofraglen, output_len;
403 unsigned char *pbuf;
404 SECStatus rv;
406 PORT_Assert (! cc->encrypt);
409 * Check that we have enough room for the output. Our caller should
410 * already handle this; failure is really an internal error (i.e. bug).
412 max_needed = NSS_CMSCipherContext_DecryptLength(cc, input_len, final);
413 PORT_Assert (max_output_len >= max_needed);
414 if (max_output_len < max_needed) {
415 /* PORT_SetError (XXX); */
416 return SECFailure;
420 * hardware encryption does not like small decryption sizes here, so we
421 * allow both blocking and padding.
423 bsize = cc->block_size;
424 padsize = cc->pad_size;
427 * When no blocking or padding work to do, we can simply call the
428 * cipher function and we are done.
430 if (bsize == 0) {
431 return (* cc->doit) (cc->cx, output, output_len_p, max_output_len,
432 input, input_len);
435 pcount = cc->pending_count;
436 pbuf = cc->pending_buf;
438 output_len = 0;
440 if (pcount) {
442 * Try to fill in an entire block, starting with the bytes
443 * we already have saved away.
445 while (input_len && pcount < bsize) {
446 pbuf[pcount++] = *input++;
447 input_len--;
450 * If we have at most a whole block and this is not our last call,
451 * then we are done for now. (We do not try to decrypt a lone
452 * single block because we cannot interpret the padding bytes
453 * until we know we are handling the very last block of all input.)
455 if (input_len == 0 && !final) {
456 cc->pending_count = pcount;
457 if (output_len_p)
458 *output_len_p = 0;
459 return SECSuccess;
462 * Given the logic above, we expect to have a full block by now.
463 * If we do not, there is something wrong, either with our own
464 * logic or with (length of) the data given to us.
466 if ((padsize != 0) && (pcount % padsize) != 0) {
467 PORT_Assert (final);
468 PORT_SetError (SEC_ERROR_BAD_DATA);
469 return SECFailure;
472 * Decrypt the block.
474 rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
475 pbuf, pcount);
476 if (rv != SECSuccess)
477 return rv;
480 * For now anyway, all of our ciphers have the same number of
481 * bytes of output as they do input. If this ever becomes untrue,
482 * then NSS_CMSCipherContext_DecryptLength needs to be made smarter!
484 PORT_Assert(ofraglen == pcount);
487 * Account for the bytes now in output.
489 max_output_len -= ofraglen;
490 output_len += ofraglen;
491 output += ofraglen;
495 * If this is our last call, we expect to have an exact number of
496 * blocks left to be decrypted; we will decrypt them all.
498 * If not our last call, we always save between 1 and bsize bytes
499 * until next time. (We must do this because we cannot be sure
500 * that none of the decrypted bytes are padding bytes until we
501 * have at least another whole block of data. You cannot tell by
502 * looking -- the data could be anything -- you can only tell by
503 * context, knowing you are looking at the last block.) We could
504 * decrypt a whole block now but it is easier if we just treat it
505 * the same way we treat partial block bytes.
507 if (final) {
508 if (padsize) {
509 blocks = input_len / padsize;
510 ifraglen = blocks * padsize;
511 } else ifraglen = input_len;
512 PORT_Assert (ifraglen == input_len);
514 if (ifraglen != input_len) {
515 PORT_SetError(SEC_ERROR_BAD_DATA);
516 return SECFailure;
518 } else {
519 blocks = (input_len - 1) / bsize;
520 ifraglen = blocks * bsize;
521 PORT_Assert (ifraglen < input_len);
523 pcount = input_len - ifraglen;
524 PORT_Memcpy (pbuf, input + ifraglen, pcount);
525 cc->pending_count = pcount;
528 if (ifraglen) {
529 rv = (* cc->doit)(cc->cx, output, &ofraglen, max_output_len,
530 input, ifraglen);
531 if (rv != SECSuccess)
532 return rv;
535 * For now anyway, all of our ciphers have the same number of
536 * bytes of output as they do input. If this ever becomes untrue,
537 * then sec_PKCS7DecryptLength needs to be made smarter!
539 PORT_Assert (ifraglen == ofraglen);
540 if (ifraglen != ofraglen) {
541 PORT_SetError(SEC_ERROR_BAD_DATA);
542 return SECFailure;
545 output_len += ofraglen;
546 } else {
547 ofraglen = 0;
551 * If we just did our very last block, "remove" the padding by
552 * adjusting the output length.
554 if (final && (padsize != 0)) {
555 unsigned int padlen = *(output + ofraglen - 1);
557 if (padlen == 0 || padlen > padsize) {
558 PORT_SetError(SEC_ERROR_BAD_DATA);
559 return SECFailure;
561 output_len -= padlen;
564 PORT_Assert (output_len_p != NULL || output_len == 0);
565 if (output_len_p != NULL)
566 *output_len_p = output_len;
568 return SECSuccess;
572 * NSS_CMSCipherContext_Encrypt - do the encryption
574 * cc - the cipher context
575 * output - buffer for decrypted result bytes
576 * output_len_p - number of bytes in output
577 * max_output_len - upper bound on bytes to put into output
578 * input - pointer to input bytes
579 * input_len - number of input bytes
580 * final - true if this is the final chunk of data
582 * Encrypts a given length of input buffer (starting at "input" and
583 * containing "input_len" bytes), placing the encrypted bytes in
584 * "output" and storing the output length in "*output_len_p".
585 * "cc" is the return value from NSS_CMSCipher_StartEncrypt.
586 * When "final" is true, this is the last of the data to be encrypted.
588 * This is much more complicated than it sounds when the cipher is
589 * a block-type, meaning that the encryption function will only
590 * operate on whole blocks. But our caller is operating stream-wise,
591 * and can pass in any number of bytes. So we need to keep track
592 * of block boundaries. We save excess bytes between calls in "cc".
593 * We also need to add padding bytes at the end. PKCS #7 specifies
594 * that the padding used for a block cipher is a string of bytes,
595 * each of whose value is the same as the length of the padding,
596 * and that all data is padded. (Even data that starts out with
597 * an exact multiple of blocks gets added to it another block,
598 * all of which is padding.)
600 * XXX I would kind of like to combine this with the function above
601 * which does decryption, since they have a lot in common. But the
602 * tricky parts about padding and filling blocks would be much
603 * harder to read that way, so I left them separate. At least for
604 * now until it is clear that they are right.
606 SECStatus
607 NSS_CMSCipherContext_Encrypt(NSSCMSCipherContext *cc, unsigned char *output,
608 unsigned int *output_len_p, unsigned int max_output_len,
609 const unsigned char *input, unsigned int input_len,
610 PRBool final)
612 int blocks, bsize, padlen, pcount, padsize;
613 unsigned int max_needed, ifraglen, ofraglen, output_len;
614 unsigned char *pbuf;
615 SECStatus rv;
617 PORT_Assert (cc->encrypt);
620 * Check that we have enough room for the output. Our caller should
621 * already handle this; failure is really an internal error (i.e. bug).
623 max_needed = NSS_CMSCipherContext_EncryptLength (cc, input_len, final);
624 PORT_Assert (max_output_len >= max_needed);
625 if (max_output_len < max_needed) {
626 /* PORT_SetError (XXX); */
627 return SECFailure;
630 bsize = cc->block_size;
631 padsize = cc->pad_size;
634 * When no blocking and padding work to do, we can simply call the
635 * cipher function and we are done.
637 if (bsize == 0) {
638 return (*cc->doit)(cc->cx, output, output_len_p, max_output_len,
639 input, input_len);
642 pcount = cc->pending_count;
643 pbuf = cc->pending_buf;
645 output_len = 0;
647 if (pcount) {
649 * Try to fill in an entire block, starting with the bytes
650 * we already have saved away.
652 while (input_len && pcount < bsize) {
653 pbuf[pcount++] = *input++;
654 input_len--;
657 * If we do not have a full block and we know we will be
658 * called again, then we are done for now.
660 if (pcount < bsize && !final) {
661 cc->pending_count = pcount;
662 if (output_len_p != NULL)
663 *output_len_p = 0;
664 return SECSuccess;
667 * If we have a whole block available, encrypt it.
669 if ((padsize == 0) || (pcount % padsize) == 0) {
670 rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
671 pbuf, pcount);
672 if (rv != SECSuccess)
673 return rv;
676 * For now anyway, all of our ciphers have the same number of
677 * bytes of output as they do input. If this ever becomes untrue,
678 * then sec_PKCS7EncryptLength needs to be made smarter!
680 PORT_Assert (ofraglen == pcount);
683 * Account for the bytes now in output.
685 max_output_len -= ofraglen;
686 output_len += ofraglen;
687 output += ofraglen;
689 pcount = 0;
693 if (input_len) {
694 PORT_Assert (pcount == 0);
696 blocks = input_len / bsize;
697 ifraglen = blocks * bsize;
699 if (ifraglen) {
700 rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
701 input, ifraglen);
702 if (rv != SECSuccess)
703 return rv;
706 * For now anyway, all of our ciphers have the same number of
707 * bytes of output as they do input. If this ever becomes untrue,
708 * then sec_PKCS7EncryptLength needs to be made smarter!
710 PORT_Assert (ifraglen == ofraglen);
712 max_output_len -= ofraglen;
713 output_len += ofraglen;
714 output += ofraglen;
717 pcount = input_len - ifraglen;
718 PORT_Assert (pcount < bsize);
719 if (pcount)
720 PORT_Memcpy (pbuf, input + ifraglen, pcount);
723 if (final) {
724 padlen = padsize - (pcount % padsize);
725 PORT_Memset (pbuf + pcount, padlen, padlen);
726 rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
727 pbuf, pcount+padlen);
728 if (rv != SECSuccess)
729 return rv;
732 * For now anyway, all of our ciphers have the same number of
733 * bytes of output as they do input. If this ever becomes untrue,
734 * then sec_PKCS7EncryptLength needs to be made smarter!
736 PORT_Assert (ofraglen == (pcount+padlen));
737 output_len += ofraglen;
738 } else {
739 cc->pending_count = pcount;
742 PORT_Assert (output_len_p != NULL || output_len == 0);
743 if (output_len_p != NULL)
744 *output_len_p = output_len;
746 return SECSuccess;