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

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. #include "pkcs12.h"
  34. #include "plarena.h"
  35. #include "secpkcs7.h"
  36. #include "p12local.h"
  37. #include "secoid.h"
  38. #include "secitem.h"
  39. #include "secport.h"
  40. #include "secasn1.h"
  41. #include "secder.h"
  42. #include "secerr.h"
  43. #include "cert.h"
  44. #include "certdb.h"
  45. #include "p12plcy.h"
  46. #include "p12.h"
  47. /* PFX extraction and validation routines */
  48. /* decode the DER encoded PFX item.  if unable to decode, check to see if it
  49.  * is an older PFX item.  If that fails, assume the file was not a valid
  50.  * pfx file.
  51.  * the returned pfx structure should be destroyed using SEC_PKCS12DestroyPFX
  52.  */
  53. static SEC_PKCS12PFXItem *
  54. sec_pkcs12_decode_pfx(SECItem *der_pfx)
  55. {
  56.     SEC_PKCS12PFXItem *pfx;
  57.     SECStatus rv;
  58.     if(der_pfx == NULL) {
  59. return NULL;
  60.     }
  61.     /* allocate the space for a new PFX item */
  62.     pfx = sec_pkcs12_new_pfx();
  63.     if(pfx == NULL) {
  64. return NULL;
  65.     }
  66.     rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate, 
  67.          der_pfx);
  68.     /* if a failure occurred, check for older version...
  69.      * we also get rid of the old pfx structure, because we don't
  70.      * know where it failed and what data in may contain
  71.      */
  72.     if(rv != SECSuccess) {
  73. SEC_PKCS12DestroyPFX(pfx);
  74. pfx = sec_pkcs12_new_pfx();
  75. if(pfx == NULL) {
  76.     return NULL;
  77. }
  78. rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate_OLD, 
  79. der_pfx);
  80. if(rv != SECSuccess) {
  81.     PORT_SetError(SEC_ERROR_PKCS12_DECODING_PFX);
  82.     PORT_FreeArena(pfx->poolp, PR_TRUE);
  83.     return NULL;
  84. }
  85. pfx->old = PR_TRUE;
  86. SGN_CopyDigestInfo(pfx->poolp, &pfx->macData.safeMac, &pfx->old_safeMac);
  87. SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, &pfx->old_macSalt);
  88.     } else {
  89. pfx->old = PR_FALSE;
  90.     }
  91.     /* convert bit string from bits to bytes */
  92.     pfx->macData.macSalt.len /= 8;
  93.     return pfx;
  94. }
  95. /* validate the integrity MAC used in the PFX.  The MAC is generated
  96.  * per the PKCS 12 document.  If the MAC is incorrect, it is most likely
  97.  * due to an invalid password.
  98.  * pwitem is the integrity password
  99.  * pfx is the decoded pfx item
  100.  */
  101. static PRBool 
  102. sec_pkcs12_check_pfx_mac(SEC_PKCS12PFXItem *pfx,
  103.  SECItem *pwitem)
  104. {
  105.     SECItem *key = NULL, *mac = NULL, *data = NULL;
  106.     SECItem *vpwd = NULL;
  107.     SECOidTag algorithm;
  108.     PRBool ret = PR_FALSE;
  109.     if(pfx == NULL) {
  110. return PR_FALSE;
  111.     }
  112.     algorithm = SECOID_GetAlgorithmTag(&pfx->macData.safeMac.digestAlgorithm);
  113.     switch(algorithm) {
  114. /* only SHA1 hashing supported as a MACing algorithm */
  115. case SEC_OID_SHA1:
  116.     if(pfx->old == PR_FALSE) {
  117. pfx->swapUnicode = PR_FALSE;
  118.     }
  119. recheckUnicodePassword:
  120.     vpwd = sec_pkcs12_create_virtual_password(pwitem, 
  121.      &pfx->macData.macSalt, 
  122. pfx->swapUnicode);
  123.     if(vpwd == NULL) {
  124. return PR_FALSE;
  125.     }
  126.     key = sec_pkcs12_generate_key_from_password(algorithm,
  127. &pfx->macData.macSalt, 
  128. (pfx->old ? pwitem : vpwd));
  129.     /* free vpwd only for newer PFX */
  130.     if(vpwd) {
  131. SECITEM_ZfreeItem(vpwd, PR_TRUE);
  132.     }
  133.     if(key == NULL) {
  134. return PR_FALSE;
  135.     }
  136.     data = SEC_PKCS7GetContent(&pfx->authSafe);
  137.     if(data == NULL) {
  138. break;
  139.     }
  140.     /* check MAC */
  141.     mac = sec_pkcs12_generate_mac(key, data, pfx->old);
  142.     ret = PR_TRUE;
  143.     if(mac) {
  144. SECItem *safeMac = &pfx->macData.safeMac.digest;
  145. if(SECITEM_CompareItem(mac, safeMac) != SECEqual) {
  146.     /* if we encounter an invalid mac, lets invert the
  147.      * password in case of unicode changes 
  148.      */
  149.     if(((!pfx->old) && pfx->swapUnicode) || (pfx->old)){
  150. PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
  151. ret = PR_FALSE;
  152.     } else {
  153. SECITEM_ZfreeItem(mac, PR_TRUE);
  154. pfx->swapUnicode = PR_TRUE;
  155. goto recheckUnicodePassword;
  156.     }
  157. SECITEM_ZfreeItem(mac, PR_TRUE);
  158.     } else {
  159. ret = PR_FALSE;
  160.     }
  161.     break;
  162. default:
  163.     PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM);
  164.     ret = PR_FALSE;
  165.     break;
  166.     }
  167.     /* let success fall through */
  168.     if(key != NULL)
  169. SECITEM_ZfreeItem(key, PR_TRUE);
  170.     return ret;
  171. }
  172. /* check the validity of the pfx structure.  we currently only support
  173.  * password integrity mode, so we check the MAC.
  174.  */
  175. static PRBool 
  176. sec_pkcs12_validate_pfx(SEC_PKCS12PFXItem *pfx, 
  177. SECItem *pwitem)
  178. {
  179.     SECOidTag contentType;
  180.     contentType = SEC_PKCS7ContentType(&pfx->authSafe);
  181.     switch(contentType)
  182.     {
  183. case SEC_OID_PKCS7_DATA:
  184.     return sec_pkcs12_check_pfx_mac(pfx, pwitem);
  185.     break;
  186. case SEC_OID_PKCS7_SIGNED_DATA:
  187. default:
  188.     PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
  189.     break;
  190.     }
  191.     return PR_FALSE;
  192. }
  193. /* decode and return the valid PFX.  if the PFX item is not valid,
  194.  * NULL is returned.
  195.  */
  196. static SEC_PKCS12PFXItem *
  197. sec_pkcs12_get_pfx(SECItem *pfx_data, 
  198.    SECItem *pwitem)
  199. {
  200.     SEC_PKCS12PFXItem *pfx;
  201.     PRBool valid_pfx;
  202.     if((pfx_data == NULL) || (pwitem == NULL)) {
  203. return NULL;
  204.     }
  205.     pfx = sec_pkcs12_decode_pfx(pfx_data);
  206.     if(pfx == NULL) {
  207. return NULL;
  208.     }
  209.     valid_pfx = sec_pkcs12_validate_pfx(pfx, pwitem);
  210.     if(valid_pfx != PR_TRUE) {
  211. SEC_PKCS12DestroyPFX(pfx);
  212. pfx = NULL;
  213.     }
  214.     return pfx;
  215. }
  216. /* authenticated safe decoding, validation, and access routines
  217.  */
  218. /* convert dogbert beta 3 authenticated safe structure to a post
  219.  * beta three structure, so that we don't have to change more routines.
  220.  */
  221. static SECStatus
  222. sec_pkcs12_convert_old_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
  223. {
  224.     SEC_PKCS12Baggage *baggage;
  225.     SEC_PKCS12BaggageItem *bag;
  226.     SECStatus rv = SECSuccess;
  227.     if(asafe->old_baggage.espvks == NULL) {
  228. /* XXX should the ASN1 engine produce a single NULL element list
  229.  * rather than setting the pointer to NULL?  
  230.  * There is no need to return an error -- assume that the list
  231.  * was empty.
  232.  */
  233. return SECSuccess;
  234.     }
  235.     baggage = sec_pkcs12_create_baggage(asafe->poolp);
  236.     if(!baggage) {
  237. return SECFailure;
  238.     }
  239.     bag = sec_pkcs12_create_external_bag(baggage);
  240.     if(!bag) {
  241. return SECFailure;
  242.     }
  243.     PORT_Memcpy(&asafe->baggage, baggage, sizeof(SEC_PKCS12Baggage));
  244.     /* if there are shrouded keys, append them to the bag */
  245.     rv = SECSuccess;
  246.     if(asafe->old_baggage.espvks[0] != NULL) {
  247. int nEspvk = 0;
  248. rv = SECSuccess;
  249. while((asafe->old_baggage.espvks[nEspvk] != NULL) && 
  250. (rv == SECSuccess)) {
  251.     rv = sec_pkcs12_append_shrouded_key(bag, 
  252.      asafe->old_baggage.espvks[nEspvk]);
  253.     nEspvk++;
  254. }
  255.     }
  256.     return rv;
  257. }    
  258. /* decodes the authenticated safe item.  a return of NULL indicates
  259.  * an error.  however, the error will have occured either in memory
  260.  * allocation or in decoding the authenticated safe.
  261.  *
  262.  * if an old PFX item has been found, we want to convert the
  263.  * old authenticated safe to the new one.
  264.  */
  265. static SEC_PKCS12AuthenticatedSafe *
  266. sec_pkcs12_decode_authenticated_safe(SEC_PKCS12PFXItem *pfx) 
  267. {
  268.     SECItem *der_asafe = NULL;
  269.     SEC_PKCS12AuthenticatedSafe *asafe = NULL;
  270.     SECStatus rv;
  271.     if(pfx == NULL) {
  272. return NULL;
  273.     }
  274.     der_asafe = SEC_PKCS7GetContent(&pfx->authSafe);
  275.     if(der_asafe == NULL) {
  276. /* XXX set error ? */
  277. goto loser;
  278.     }
  279.     asafe = sec_pkcs12_new_asafe(pfx->poolp);
  280.     if(asafe == NULL) {
  281. goto loser;
  282.     }
  283.     if(pfx->old == PR_FALSE) {
  284. rv = SEC_ASN1DecodeItem(pfx->poolp, asafe, 
  285.   SEC_PKCS12AuthenticatedSafeTemplate, 
  286.   der_asafe);
  287. asafe->old = PR_FALSE;
  288. asafe->swapUnicode = pfx->swapUnicode;
  289.     } else {
  290. /* handle beta exported files */
  291. rv = SEC_ASN1DecodeItem(pfx->poolp, asafe, 
  292. SEC_PKCS12AuthenticatedSafeTemplate_OLD,
  293. der_asafe);
  294. asafe->safe = &(asafe->old_safe);
  295. rv = sec_pkcs12_convert_old_auth_safe(asafe);
  296. asafe->old = PR_TRUE;
  297.     }
  298.     if(rv != SECSuccess) {
  299. goto loser;
  300.     }
  301.     asafe->poolp = pfx->poolp;
  302.     
  303.     return asafe;
  304. loser:
  305.     return NULL;
  306. }
  307. /* validates the safe within the authenticated safe item.  
  308.  * in order to be valid:
  309.  *  1.  the privacy salt must be present
  310.  *  2.  the encryption algorithm must be supported (including
  311.  * export policy)
  312.  * PR_FALSE indicates an error, PR_TRUE indicates a valid safe
  313.  */
  314. static PRBool 
  315. sec_pkcs12_validate_encrypted_safe(SEC_PKCS12AuthenticatedSafe *asafe)
  316. {
  317.     PRBool valid = PR_FALSE;
  318.     SECAlgorithmID *algid;
  319.     if(asafe == NULL) {
  320. return PR_FALSE;
  321.     }
  322.     /* if mode is password privacy, then privacySalt is assumed
  323.      * to be non-zero.
  324.      */
  325.     if(asafe->privacySalt.len != 0) {
  326. valid = PR_TRUE;
  327. asafe->privacySalt.len /= 8;
  328.     } else {
  329. PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
  330. return PR_FALSE;
  331.     }
  332.     /* until spec changes, content will have between 2 and 8 bytes depending
  333.      * upon the algorithm used if certs are unencrypted...
  334.      * also want to support case where content is empty -- which we produce 
  335.      */ 
  336.     if(SEC_PKCS7IsContentEmpty(asafe->safe, 8) == PR_TRUE) {
  337. asafe->emptySafe = PR_TRUE;
  338. return PR_TRUE;
  339.     }
  340.     asafe->emptySafe = PR_FALSE;
  341.     /* make sure that a pbe algorithm is being used */
  342.     algid = SEC_PKCS7GetEncryptionAlgorithm(asafe->safe);
  343.     if(algid != NULL) {
  344. if(SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
  345.     valid = SEC_PKCS12DecryptionAllowed(algid);
  346.     if(valid == PR_FALSE) {
  347. PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
  348.     }
  349. } else {
  350.     PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
  351.     valid = PR_FALSE;
  352. }
  353.     } else {
  354. valid = PR_FALSE;
  355. PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
  356.     }
  357.     return valid;
  358. }
  359. /* validates authenticates safe:
  360.  *  1.  checks that the version is supported
  361.  *  2.  checks that only password privacy mode is used (currently)
  362.  *  3.  further, makes sure safe has appropriate policies per above function
  363.  * PR_FALSE indicates failure.
  364.  */
  365. static PRBool 
  366. sec_pkcs12_validate_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
  367. {
  368.     PRBool valid = PR_TRUE;
  369.     SECOidTag safe_type;
  370.     int version;
  371.     if(asafe == NULL) {
  372. return PR_FALSE;
  373.     }
  374.     /* check version, since it is default it may not be present.
  375.      * therefore, assume ok
  376.      */
  377.     if((asafe->version.len > 0) && (asafe->old == PR_FALSE)) {
  378. version = DER_GetInteger(&asafe->version);
  379. if(version > SEC_PKCS12_PFX_VERSION) {
  380.     PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION);
  381.     return PR_FALSE;
  382. }
  383.     }
  384.     /* validate password mode is being used */
  385.     safe_type = SEC_PKCS7ContentType(asafe->safe);
  386.     switch(safe_type)
  387.     {
  388. case SEC_OID_PKCS7_ENCRYPTED_DATA:
  389.     valid = sec_pkcs12_validate_encrypted_safe(asafe);
  390.     break;
  391. case SEC_OID_PKCS7_ENVELOPED_DATA:
  392. default:
  393.     PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
  394.     valid = PR_FALSE;
  395.     break;
  396.     }
  397.     return valid;
  398. }
  399. /* retrieves the authenticated safe item from the PFX item
  400.  *  before returning the authenticated safe, the validity of the
  401.  *  authenticated safe is checked and if valid, returned.
  402.  * a return of NULL indicates that an error occured.
  403.  */
  404. static SEC_PKCS12AuthenticatedSafe *
  405. sec_pkcs12_get_auth_safe(SEC_PKCS12PFXItem *pfx)
  406. {
  407.     SEC_PKCS12AuthenticatedSafe *asafe;
  408.     PRBool valid_safe;
  409.     if(pfx == NULL) {
  410. return NULL;
  411.     }
  412.     asafe = sec_pkcs12_decode_authenticated_safe(pfx);
  413.     if(asafe == NULL) {
  414. return NULL;
  415.     }
  416.     valid_safe = sec_pkcs12_validate_auth_safe(asafe);
  417.     if(valid_safe != PR_TRUE) {
  418. asafe = NULL;
  419.     } else if(asafe) {
  420. asafe->baggage.poolp = asafe->poolp;
  421.     }
  422.     return asafe;
  423. }
  424. /* decrypts the authenticated safe.
  425.  * a return of anything but SECSuccess indicates an error.  the
  426.  * password is not known to be valid until the call to the 
  427.  * function sec_pkcs12_get_safe_contents.  If decoding the safe
  428.  * fails, it is assumed the password was incorrect and the error
  429.  * is set then.  any failure here is assumed to be due to 
  430.  * internal problems in SEC_PKCS7DecryptContents or below.
  431.  */
  432. static SECStatus
  433. sec_pkcs12_decrypt_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe, 
  434.      SECItem *pwitem,
  435.      void *wincx)
  436. {
  437.     SECStatus rv = SECFailure;
  438.     SECItem *vpwd = NULL;
  439.     if((asafe == NULL) || (pwitem == NULL)) {
  440. return SECFailure;
  441.     }
  442.     if(asafe->old == PR_FALSE) {
  443. vpwd = sec_pkcs12_create_virtual_password(pwitem, &asafe->privacySalt,
  444.  asafe->swapUnicode);
  445. if(vpwd == NULL) {
  446.     return SECFailure;
  447. }
  448.     }
  449.     rv = SEC_PKCS7DecryptContents(asafe->poolp, asafe->safe, 
  450.        (asafe->old ? pwitem : vpwd), wincx);
  451.     if(asafe->old == PR_FALSE) {
  452. SECITEM_ZfreeItem(vpwd, PR_TRUE);
  453.     }
  454.     return rv;
  455. }
  456. /* extract the safe from the authenticated safe.
  457.  *  if we are unable to decode the safe, then it is likely that the 
  458.  *  safe has not been decrypted or the password used to decrypt
  459.  *  the safe was invalid.  we assume that the password was invalid and
  460.  *  set an error accordingly.
  461.  * a return of NULL indicates that an error occurred.
  462.  */
  463. static SEC_PKCS12SafeContents *
  464. sec_pkcs12_get_safe_contents(SEC_PKCS12AuthenticatedSafe *asafe)
  465. {
  466.     SECItem *src = NULL;
  467.     SEC_PKCS12SafeContents *safe = NULL;
  468.     SECStatus rv = SECFailure;
  469.     if(asafe == NULL) {
  470. return NULL;
  471.     }
  472.     safe = (SEC_PKCS12SafeContents *)PORT_ArenaZAlloc(asafe->poolp, 
  473.      sizeof(SEC_PKCS12SafeContents));
  474.     if(safe == NULL) {
  475. return NULL;
  476.     }
  477.     safe->poolp = asafe->poolp;
  478.     safe->old = asafe->old;
  479.     safe->swapUnicode = asafe->swapUnicode;
  480.     src = SEC_PKCS7GetContent(asafe->safe);
  481.     if(src != NULL) {
  482. const SEC_ASN1Template *theTemplate;
  483. if(asafe->old != PR_TRUE) {
  484.     theTemplate = SEC_PKCS12SafeContentsTemplate;
  485. } else {
  486.     theTemplate = SEC_PKCS12SafeContentsTemplate_OLD;
  487. }
  488. rv = SEC_ASN1DecodeItem(asafe->poolp, safe, theTemplate, src);
  489. /* if we could not decode the item, password was probably invalid */
  490. if(rv != SECSuccess) {
  491.     safe = NULL;
  492.     PORT_SetError(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT);
  493. }
  494.     } else {
  495. PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
  496. rv = SECFailure;
  497.     }
  498.     return safe;
  499. }
  500. /* import PFX item 
  501.  * der_pfx is the der encoded pfx structure
  502.  * pbef and pbearg are the integrity/encryption password call back
  503.  * ncCall is the nickname collision calllback
  504.  * slot is the destination token
  505.  * wincx window handler
  506.  *
  507.  * on error, error code set and SECFailure returned 
  508.  */
  509. SECStatus
  510. SEC_PKCS12PutPFX(SECItem *der_pfx, SECItem *pwitem,
  511.  SEC_PKCS12NicknameCollisionCallback ncCall,
  512.  PK11SlotInfo *slot,
  513.  void *wincx)
  514. {
  515.     SEC_PKCS12PFXItem *pfx;
  516.     SEC_PKCS12AuthenticatedSafe *asafe;
  517.     SEC_PKCS12SafeContents *safe_contents = NULL;
  518.     SECStatus rv;
  519.     if(!der_pfx || !pwitem || !slot) {
  520. return SECFailure;
  521.     }
  522.     /* decode and validate each section */
  523.     rv = SECFailure;
  524.     pfx = sec_pkcs12_get_pfx(der_pfx, pwitem);
  525.     if(pfx != NULL) {
  526. asafe = sec_pkcs12_get_auth_safe(pfx);
  527. if(asafe != NULL) {
  528.     /* decrypt safe -- only if not empty */
  529.     if(asafe->emptySafe != PR_TRUE) {
  530. rv = sec_pkcs12_decrypt_auth_safe(asafe, pwitem, wincx);
  531. if(rv == SECSuccess) {
  532.     safe_contents = sec_pkcs12_get_safe_contents(asafe);
  533.     if(safe_contents == NULL) {
  534. rv = SECFailure;
  535.     }
  536. }
  537.     } else {
  538. safe_contents = sec_pkcs12_create_safe_contents(asafe->poolp);
  539. safe_contents->swapUnicode = pfx->swapUnicode;
  540. if(safe_contents == NULL) {
  541.     rv = SECFailure;
  542. } else {
  543.     rv = SECSuccess;
  544. }
  545.     }
  546.     /* get safe contents and begin import */
  547.     if(rv == SECSuccess) {
  548. SEC_PKCS12DecoderContext *p12dcx;
  549. p12dcx = sec_PKCS12ConvertOldSafeToNew(pfx->poolp, slot,
  550. pfx->swapUnicode,
  551. pwitem, wincx, safe_contents,
  552. &asafe->baggage);
  553. if(!p12dcx) {
  554.     rv = SECFailure;
  555.     goto loser;
  556. }
  557. if(SEC_PKCS12DecoderValidateBags(p12dcx, ncCall) 
  558. != SECSuccess) {
  559.     rv = SECFailure;
  560.     goto loser;
  561. }
  562. rv = SEC_PKCS12DecoderImportBags(p12dcx);
  563.     }
  564. }
  565.     }
  566. loser:
  567.     if(pfx) {
  568. SEC_PKCS12DestroyPFX(pfx);
  569.     }
  570.     return rv;
  571. }
  572. PRBool 
  573. SEC_PKCS12ValidData(char *buf, int bufLen, long int totalLength)
  574. {
  575.     int lengthLength;
  576.     PRBool valid = PR_FALSE;
  577.     if(buf == NULL) {
  578. return PR_FALSE;
  579.     }
  580.     /* check for constructed sequence identifier tag */
  581.     if(*buf == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) {
  582. totalLength--;   /* header byte taken care of */
  583. buf++;
  584. lengthLength = (long int)SEC_ASN1LengthLength(totalLength - 1);
  585. if(totalLength > 0x7f) {
  586.     lengthLength--;
  587.     *buf &= 0x7f;  /* remove bit 8 indicator */
  588.     if((*buf - (char)lengthLength) == 0) {
  589. valid = PR_TRUE;
  590.     }
  591. } else {
  592.     lengthLength--;
  593.     if((*buf - (char)lengthLength) == 0) {
  594. valid = PR_TRUE;
  595.     }
  596. }
  597.     }
  598.     return valid;
  599. }