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

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 "cryptohi.h"
  34. #include "keyhi.h"
  35. #include "secrng.h"
  36. #include "secoid.h"
  37. #include "secitem.h"
  38. #include "secder.h"
  39. #include "base64.h"
  40. #include "secasn1.h"
  41. #include "cert.h"
  42. #include "pk11func.h"
  43. #include "secerr.h"
  44. #include "secdig.h"
  45. #include "prtime.h"
  46. const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
  47.     { SEC_ASN1_SEQUENCE,
  48.   0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
  49.     { SEC_ASN1_INLINE,
  50.   offsetof(CERTSubjectPublicKeyInfo,algorithm),
  51.   SECOID_AlgorithmIDTemplate },
  52.     { SEC_ASN1_BIT_STRING,
  53.   offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
  54.     { 0, }
  55. };
  56. const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
  57. {
  58.     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
  59.     { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) },
  60.     { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) },
  61.     { 0 }
  62. };
  63. const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
  64.     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
  65.     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), },
  66.     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), },
  67.     { 0, }
  68. };
  69. const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
  70.     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), },
  71.     { 0, }
  72. };
  73. const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
  74.     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
  75.     { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
  76.     { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
  77.     { SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
  78.     { 0, }
  79. };
  80. const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
  81.     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },
  82.     { 0, }
  83. };
  84. const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
  85.     { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(SECKEYPublicKey) },
  86.     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },
  87.     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },
  88.     /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
  89.     { SEC_ASN1_SKIP_REST },
  90.     { 0, }
  91. };
  92. const SEC_ASN1Template SECKEY_FortezzaParameterTemplate[] = {
  93.     { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(PQGParams) },
  94.     { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,prime), },
  95.     { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,subPrime), },
  96.     { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,base), },
  97.     { 0 },
  98. };
  99.  
  100. const SEC_ASN1Template SECKEY_FortezzaDiffParameterTemplate[] = {
  101.     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(DiffPQGParams) },
  102.     { SEC_ASN1_INLINE, offsetof(DiffPQGParams,DiffKEAParams), 
  103.                        SECKEY_FortezzaParameterTemplate},
  104.     { SEC_ASN1_INLINE, offsetof(DiffPQGParams,DiffDSAParams), 
  105.                        SECKEY_FortezzaParameterTemplate},
  106.     { 0 },
  107. };
  108. const SEC_ASN1Template SECKEY_FortezzaPreParamTemplate[] = {
  109.     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
  110.       SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(PQGDualParams,CommParams),
  111.                 SECKEY_FortezzaParameterTemplate},
  112.     { 0, }
  113. };
  114. const SEC_ASN1Template SECKEY_FortezzaAltPreParamTemplate[] = {
  115.     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
  116.       SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(PQGDualParams,DiffParams),
  117.                 SECKEY_FortezzaDiffParameterTemplate},
  118.     { 0, }
  119. };
  120. const SEC_ASN1Template SECKEY_KEAPublicKeyTemplate[] = {
  121.     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.kea.publicValue), },
  122.     { 0, }
  123. };
  124. const SEC_ASN1Template SECKEY_KEAParamsTemplate[] = {
  125.     { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPublicKey,u.kea.params.hash), }, 
  126.     { 0, }
  127. };
  128. /*
  129.  * NOTE: This only generates RSA Private Key's. If you need more,
  130.  * We need to pass in some more params...
  131.  */
  132. SECKEYPrivateKey *
  133. SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx)
  134. {
  135.     SECKEYPrivateKey *privk;
  136.     PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx);
  137.     PK11RSAGenParams param;
  138.     param.keySizeInBits = keySizeInBits;
  139.     param.pe = 65537L;
  140.     
  141.     privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,&param,pubk,
  142. PR_FALSE, PR_TRUE, cx);
  143.     PK11_FreeSlot(slot);
  144.     return(privk);
  145. }
  146. void
  147. SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
  148. {
  149.     if (privk) {
  150. if (privk->pkcs11Slot) {
  151.     if (privk->pkcs11IsTemp) {
  152.      PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID);
  153.     }
  154.     PK11_FreeSlot(privk->pkcs11Slot);
  155. }
  156.      if (privk->arena) {
  157.     PORT_FreeArena(privk->arena, PR_TRUE);
  158. }
  159.     }
  160. }
  161. void
  162. SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
  163. {
  164.     if (pubk) {
  165. if (pubk->pkcs11Slot) {
  166.     PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID);
  167.     PK11_FreeSlot(pubk->pkcs11Slot);
  168. }
  169.      if (pubk->arena) {
  170.     PORT_FreeArena(pubk->arena, PR_FALSE);
  171. }
  172.     }
  173. }
  174. SECStatus
  175. SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena,
  176.      CERTSubjectPublicKeyInfo *to,
  177.      CERTSubjectPublicKeyInfo *from)
  178. {
  179.     SECStatus rv;
  180.     rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
  181.     if (rv == SECSuccess)
  182. rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &from->subjectPublicKey);
  183.     return rv;
  184. }
  185. SECStatus
  186. SECKEY_KEASetParams(KEAParams * params, SECKEYPublicKey * pubKey) {
  187.     if (pubKey->keyType == fortezzaKey) {
  188.         /* the key is a fortezza V1 public key  */
  189. /* obtain hash of pubkey->u.fortezza.params.prime.data +
  190.           pubkey->u.fortezza.params.subPrime.data +
  191.   pubkey->u.fortezza.params.base.data  */
  192. /* store hash in params->hash */
  193.     } else if (pubKey->keyType == keaKey) {
  194.         /* the key is a new fortezza KEA public key. */
  195.         SECITEM_CopyItem(pubKey->arena, &params->hash, 
  196.                  &pubKey->u.kea.params.hash );
  197.     } else {
  198. /* the key has no KEA parameters */
  199. return SECFailure;
  200.     }
  201. }
  202. SECStatus
  203. SECKEY_KEAParamCompare(CERTCertificate *cert1,CERTCertificate *cert2) 
  204. {
  205.     SECStatus rv;
  206.     SECOidData *oid=NULL;
  207.     CERTSubjectPublicKeyInfo * subjectSpki=NULL;
  208.     CERTSubjectPublicKeyInfo * issuerSpki=NULL;
  209.     CERTCertificate *issuerCert = NULL;
  210.     SECKEYPublicKey *pubKey1 = 0;
  211.     SECKEYPublicKey *pubKey2 = 0;
  212.     KEAParams params1;
  213.     KEAParams params2;
  214.     rv = SECFailure;
  215.     /* get cert1's public key */
  216.     pubKey1 = CERT_ExtractPublicKey(cert1);
  217.     if ( !pubKey1 ) {
  218. return(SECFailure);
  219.     }
  220.     
  221.     /* get cert2's public key */
  222.     pubKey2 = CERT_ExtractPublicKey(cert2);
  223.     if ( !pubKey2 ) {
  224. return(SECFailure);
  225.     }
  226.     /* handle the case when both public keys are new
  227.      * fortezza KEA public keys.    */
  228.     if ((pubKey1->keyType == keaKey) &&
  229.         (pubKey2->keyType == keaKey) ) {
  230.         rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.kea.params.hash,
  231.                          &pubKey2->u.kea.params.hash);
  232. goto done;
  233.     }
  234.     /* handle the case when both public keys are old fortezza
  235.      * public keys.              */
  236.     if ((pubKey1->keyType == fortezzaKey) &&
  237.         (pubKey2->keyType == fortezzaKey) ) {
  238.         rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.prime,
  239.                          &pubKey2->u.fortezza.keaParams.prime);
  240. if (rv == SECEqual) {
  241.     rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.subPrime,
  242.                              &pubKey2->u.fortezza.keaParams.subPrime);
  243. }
  244. if (rv == SECEqual) {
  245.     rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.base,
  246.                              &pubKey2->u.fortezza.keaParams.base);
  247. }
  248. goto done;
  249.     }
  250.     /* handle the case when the public keys are a mixture of 
  251.      * old and new.                          */
  252.     rv = SECKEY_KEASetParams(&params1, pubKey1);
  253.     if (rv != SECSuccess) return rv;
  254.     rv = SECKEY_KEASetParams(&params2, pubKey2);
  255.     if (rv != SECSuccess) return rv;
  256.     rv = (SECStatus)SECITEM_CompareItem(&params1.hash, &params2.hash);
  257. done:
  258.     SECKEY_DestroyPublicKey(pubKey1);
  259.     SECKEY_DestroyPublicKey(pubKey2);
  260.     return rv;   /* returns SECEqual if parameters are equal */
  261. }
  262. /* Procedure to update the pqg parameters for a cert's public key.
  263.  * pqg parameters only need to be updated for DSA and fortezza certificates.
  264.  * The procedure uses calls to itself recursively to update a certificate
  265.  * issuer's pqg parameters.  Some important rules are:
  266.  *    - Do nothing if the cert already has PQG parameters.
  267.  *    - If the cert does not have PQG parameters, obtain them from the issuer.
  268.  *    - A valid cert chain cannot have a DSA or Fortezza cert without
  269.  *      pqg parameters that has a parent that is not a DSA or Fortezza cert.
  270.  *    - pqg paramters are stored in two different formats: the standard
  271.  *      DER encoded format and the fortezza-only wrapped format.  The params
  272.  *      should be copied from issuer to subject cert without modifying the
  273.  *      formats.  The public key extraction code will deal with the different
  274.  *      formats at the time of extraction.  */
  275. SECStatus
  276. seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count)
  277. {
  278.     SECStatus rv, rvCompare;
  279.     SECOidData *oid=NULL;
  280.     int tag;
  281.     CERTSubjectPublicKeyInfo * subjectSpki=NULL;
  282.     CERTSubjectPublicKeyInfo * issuerSpki=NULL;
  283.     CERTCertificate *issuerCert = NULL;
  284.     rv = SECSuccess;
  285.     /* increment cert chain length counter*/
  286.     count++;
  287.     /* check if cert chain length exceeds the maximum length*/
  288.     if (count > CERT_MAX_CERT_CHAIN) {
  289. return SECFailure;
  290.     }
  291.     oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);            
  292.     if (oid != NULL) {  
  293.         tag = oid->offset;
  294.              
  295.         /* Check if cert has a DSA or Fortezza public key. If not, return
  296.          * success since no PQG params need to be updated.  */
  297. if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&
  298.      (tag != SEC_OID_MISSI_DSS_OLD) &&
  299.              (tag != SEC_OID_MISSI_KEA_DSS) &&
  300.              (tag != SEC_OID_MISSI_DSS) &&               
  301.              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
  302.              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
  303.              (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) {
  304.             
  305.             return SECSuccess;
  306.         }
  307.     } else {
  308.         return SECFailure;  /* return failure if oid is NULL */  
  309.     }
  310.     /* if cert has PQG parameters, return success */
  311.     subjectSpki=&subjectCert->subjectPublicKeyInfo;
  312.     if (subjectSpki->algorithm.parameters.len != 0) {
  313.         return SECSuccess;
  314.     }
  315.     /* check if the cert is self-signed */
  316.     rvCompare = (SECStatus)SECITEM_CompareItem(&subjectCert->derSubject,
  317.     &subjectCert->derIssuer);
  318. if (rvCompare == SECEqual) {
  319.   /* fail since cert is self-signed and has no pqg params. */
  320.             return SECFailure;     
  321. }
  322.      
  323.     /* get issuer cert */
  324.     issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
  325. if ( ! issuerCert ) {
  326.             return SECFailure;
  327. }
  328.     /* if parent is not DSA or fortezza, return failure since
  329.        we don't allow this case. */
  330.     oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
  331.     if (oid != NULL) {  
  332.         tag = oid->offset;
  333.              
  334.         /* Check if issuer cert has a DSA or Fortezza public key. If not,
  335.          * return failure.   */
  336. if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&
  337.      (tag != SEC_OID_MISSI_DSS_OLD) &&
  338.              (tag != SEC_OID_MISSI_KEA_DSS) &&
  339.              (tag != SEC_OID_MISSI_DSS) &&               
  340.              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
  341.              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
  342.              (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) {
  343.             
  344.             return SECFailure;
  345.         }
  346.     } else {
  347.         return SECFailure;  /* return failure if oid is NULL */  
  348.     }
  349.     /* at this point the subject cert has no pqg parameters and the
  350.      * issuer cert has a DSA or fortezza public key.  Update the issuer's
  351.      * pqg parameters with a recursive call to this same function. */
  352.     rv = seckey_UpdateCertPQGChain(issuerCert, count);
  353.     if (rv != SECSuccess) return rv;
  354.     /* ensure issuer has pqg parameters */
  355.     issuerSpki=&issuerCert->subjectPublicKeyInfo;
  356.     if (issuerSpki->algorithm.parameters.len == 0) {
  357.         rv = SECFailure; 
  358.     }
  359.     /* if update was successful and pqg params present, then copy the
  360.      * parameters to the subject cert's key. */
  361.     if (rv == SECSuccess) {
  362.         rv = SECITEM_CopyItem(subjectCert->arena,
  363.                               &subjectSpki->algorithm.parameters, 
  364.           &issuerSpki->algorithm.parameters);
  365.     }
  366.     return rv;
  367. }
  368.  
  369. SECStatus
  370. SECKEY_UpdateCertPQG(CERTCertificate * subjectCert)
  371. {
  372.     return(seckey_UpdateCertPQGChain(subjectCert,0));
  373. }
  374.    
  375. /* Decode the PQG parameters.  The params could be stored in two
  376.  * possible formats, the old fortezza-only wrapped format or
  377.  * the standard DER encoded format.   Store the decoded parameters in an
  378.  * old fortezza cert data structure */
  379.  
  380. SECStatus
  381. SECKEY_FortezzaDecodePQGtoOld(PRArenaPool *arena, SECKEYPublicKey *pubk,
  382.                               SECItem *params) {
  383.         SECStatus rv;
  384. PQGDualParams dual_params;
  385.     if (params == NULL) return SECFailure; 
  386.     
  387.     if (params->data == NULL) return SECFailure;
  388.     /* Check if params use the standard format.
  389.      * The value 0xa1 will appear in the first byte of the parameter data
  390.      * if the PQG parameters are not using the standard format. This
  391.      * code should be changed to use a better method to detect non-standard
  392.      * parameters.    */
  393.     if ((params->data[0] != 0xa1) &&
  394.         (params->data[0] != 0xa0)) {
  395.             /* PQG params are in the standard format */
  396.     /* Store DSA PQG parameters */
  397.             rv = SEC_ASN1DecodeItem(arena, &pubk->u.fortezza.params,
  398.                               SECKEY_PQGParamsTemplate,
  399.                               params);
  400.     if (rv == SECSuccess) {
  401.         /* Copy the DSA PQG parameters to the KEA PQG parameters. */
  402.         rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
  403.                                       &pubk->u.fortezza.params.prime);
  404.                 if (rv != SECSuccess) return rv;
  405.                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
  406.                                       &pubk->u.fortezza.params.subPrime);
  407.                 if (rv != SECSuccess) return rv;
  408.                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
  409.                                       &pubk->u.fortezza.params.base);
  410.                 if (rv != SECSuccess) return rv;
  411.             }
  412.     } else {
  413. dual_params.CommParams.prime.len = 0;
  414.         dual_params.CommParams.subPrime.len = 0;
  415. dual_params.CommParams.base.len = 0;
  416. dual_params.DiffParams.DiffDSAParams.prime.len = 0;
  417.         dual_params.DiffParams.DiffDSAParams.subPrime.len = 0;
  418. dual_params.DiffParams.DiffDSAParams.base.len = 0;
  419.         /* else the old fortezza-only wrapped format is used. */
  420. if (params->data[0] == 0xa1) {
  421.             rv = SEC_ASN1DecodeItem(arena, &dual_params, 
  422. SECKEY_FortezzaPreParamTemplate, params);
  423. } else {
  424.             rv = SEC_ASN1DecodeItem(arena, &dual_params, 
  425.         SECKEY_FortezzaAltPreParamTemplate, params);
  426.         }
  427.         if (rv < 0) return rv;
  428.         if ( (dual_params.CommParams.prime.len > 0) &&
  429.              (dual_params.CommParams.subPrime.len > 0) && 
  430.              (dual_params.CommParams.base.len > 0) ) {
  431.             /* copy in common params */
  432.     
  433.     rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.prime,
  434.                                   &dual_params.CommParams.prime);
  435.             if (rv != SECSuccess) return rv;
  436.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.subPrime,
  437.                                   &dual_params.CommParams.subPrime);
  438.             if (rv != SECSuccess) return rv;
  439.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.base,
  440.                                   &dual_params.CommParams.base);
  441.     /* Copy the DSA PQG parameters to the KEA PQG parameters. */
  442.     rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
  443.                                   &pubk->u.fortezza.params.prime);
  444.             if (rv != SECSuccess) return rv;
  445.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
  446.                                   &pubk->u.fortezza.params.subPrime);
  447.             if (rv != SECSuccess) return rv;
  448.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
  449.                                   &pubk->u.fortezza.params.base);
  450.             if (rv != SECSuccess) return rv;
  451.         } else {
  452.     /* else copy in different params */
  453.     /* copy DSA PQG parameters */
  454.     rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.prime,
  455.                                   &dual_params.DiffParams.DiffDSAParams.prime);
  456.             if (rv != SECSuccess) return rv;
  457.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.subPrime,
  458.                                   &dual_params.DiffParams.DiffDSAParams.subPrime);
  459.             if (rv != SECSuccess) return rv;
  460.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.base,
  461.                                   &dual_params.DiffParams.DiffDSAParams.base);
  462.     /* copy KEA PQG parameters */
  463.     rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
  464.                                   &dual_params.DiffParams.DiffKEAParams.prime);
  465.             if (rv != SECSuccess) return rv;
  466.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
  467.                                   &dual_params.DiffParams.DiffKEAParams.subPrime);
  468.             if (rv != SECSuccess) return rv;
  469.             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
  470.                                   &dual_params.DiffParams.DiffKEAParams.base);
  471.         }
  472.        
  473.     }
  474.     return rv;
  475. }
  476. /* Decode the DSA PQG parameters.  The params could be stored in two
  477.  * possible formats, the old fortezza-only wrapped format or
  478.  * the normal standard format.  Store the decoded parameters in
  479.  * a V3 certificate data structure.  */ 
  480. SECStatus
  481. SECKEY_DSADecodePQG(PRArenaPool *arena, SECKEYPublicKey *pubk, SECItem *params) {
  482.         SECStatus rv;
  483. PQGDualParams dual_params;
  484.     if (params == NULL) return SECFailure; 
  485.     
  486.     if (params->data == NULL) return SECFailure;
  487.     /* Check if params use the standard format.
  488.      * The value 0xa1 will appear in the first byte of the parameter data
  489.      * if the PQG parameters are not using the standard format.  This
  490.      * code should be changed to use a better method to detect non-standard
  491.      * parameters.    */
  492.     if ((params->data[0] != 0xa1) &&
  493.         (params->data[0] != 0xa0)) {
  494.     
  495.          /* PQG params are in the standard format */
  496.          rv = SEC_ASN1DecodeItem(arena, &pubk->u.dsa.params,
  497.                              SECKEY_PQGParamsTemplate,
  498.                              params);
  499.     } else {
  500. dual_params.CommParams.prime.len = 0;
  501.         dual_params.CommParams.subPrime.len = 0;
  502. dual_params.CommParams.base.len = 0;
  503. dual_params.DiffParams.DiffDSAParams.prime.len = 0;
  504.         dual_params.DiffParams.DiffDSAParams.subPrime.len = 0;
  505. dual_params.DiffParams.DiffDSAParams.base.len = 0;
  506.         /* else the old fortezza-only wrapped format is used. */
  507.         if (params->data[0] == 0xa1) {
  508.             rv = SEC_ASN1DecodeItem(arena, &dual_params, 
  509. SECKEY_FortezzaPreParamTemplate, params);
  510. } else {
  511.             rv = SEC_ASN1DecodeItem(arena, &dual_params, 
  512.         SECKEY_FortezzaAltPreParamTemplate, params);
  513.         }
  514.         if (rv < 0) return rv;
  515.         if ( (dual_params.CommParams.prime.len > 0) &&
  516.              (dual_params.CommParams.subPrime.len > 0) && 
  517.              (dual_params.CommParams.base.len > 0) ) {
  518.             /* copy in common params */
  519.     
  520.     rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
  521.                                   &dual_params.CommParams.prime);
  522.             if (rv != SECSuccess) return rv;
  523.             rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
  524.                                   &dual_params.CommParams.subPrime);
  525.             if (rv != SECSuccess) return rv;
  526.             rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
  527.                                   &dual_params.CommParams.base);
  528.         } else {
  529.     /* else copy in different params */
  530.     /* copy DSA PQG parameters */
  531.     rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
  532.                                   &dual_params.DiffParams.DiffDSAParams.prime);
  533.             if (rv != SECSuccess) return rv;
  534.             rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
  535.                                   &dual_params.DiffParams.DiffDSAParams.subPrime);
  536.             if (rv != SECSuccess) return rv;
  537.             rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
  538.                                   &dual_params.DiffParams.DiffDSAParams.base);
  539.         }
  540.     }
  541.     return rv;
  542. }
  543. /* Decodes the DER encoded fortezza public key and stores the results in a
  544.  * structure of type SECKEYPublicKey. */
  545. SECStatus
  546. SECKEY_FortezzaDecodeCertKey(PRArenaPool *arena, SECKEYPublicKey *pubk,
  547.                              SECItem *rawkey, SECItem *params) {
  548. unsigned char *rawptr = rawkey->data;
  549. unsigned char *end = rawkey->data + rawkey->len;
  550. unsigned char *clearptr;
  551. /* first march down and decode the raw key data */
  552. /* version */
  553. pubk->u.fortezza.KEAversion = *rawptr++;
  554. if (*rawptr++ != 0x01) {
  555. return SECFailure;
  556. }
  557. /* KMID */
  558. PORT_Memcpy(pubk->u.fortezza.KMID,rawptr,
  559. sizeof(pubk->u.fortezza.KMID));
  560. rawptr += sizeof(pubk->u.fortezza.KMID);
  561. /* clearance (the string up to the first byte with the hi-bit on */
  562. clearptr = rawptr;
  563. while ((rawptr < end) && (*rawptr++ & 0x80));
  564. if (rawptr >= end) { return SECFailure; }
  565. pubk->u.fortezza.clearance.len = rawptr - clearptr;
  566. pubk->u.fortezza.clearance.data = 
  567. (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.clearance.len);
  568. if (pubk->u.fortezza.clearance.data == NULL) {
  569. return SECFailure;
  570. }
  571. PORT_Memcpy(pubk->u.fortezza.clearance.data,clearptr,
  572. pubk->u.fortezza.clearance.len);
  573. /* KEAPrivilege (the string up to the first byte with the hi-bit on */
  574. clearptr = rawptr;
  575. while ((rawptr < end) && (*rawptr++ & 0x80));
  576. if (rawptr >= end) { return SECFailure; }
  577. pubk->u.fortezza.KEApriviledge.len = rawptr - clearptr;
  578. pubk->u.fortezza.KEApriviledge.data = 
  579. (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.KEApriviledge.len);
  580. if (pubk->u.fortezza.KEApriviledge.data == NULL) {
  581. return SECFailure;
  582. }
  583. PORT_Memcpy(pubk->u.fortezza.KEApriviledge.data,clearptr,
  584. pubk->u.fortezza.KEApriviledge.len);
  585. /* now copy the key. The next to bytes are the key length, and the
  586.  * key follows */
  587. pubk->u.fortezza.KEAKey.len = (*rawptr << 8) | rawptr[1];
  588. rawptr += 2;
  589. if (rawptr+pubk->u.fortezza.KEAKey.len > end) { return SECFailure; }
  590. pubk->u.fortezza.KEAKey.data = 
  591. (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.KEAKey.len);
  592. if (pubk->u.fortezza.KEAKey.data == NULL) {
  593. return SECFailure;
  594. }
  595. PORT_Memcpy(pubk->u.fortezza.KEAKey.data,rawptr,
  596. pubk->u.fortezza.KEAKey.len);
  597. rawptr += pubk->u.fortezza.KEAKey.len;
  598. /* shared key */
  599. if (rawptr >= end) {
  600.     pubk->u.fortezza.DSSKey.len = pubk->u.fortezza.KEAKey.len;
  601.     /* this depends on the fact that we are going to get freed with an
  602.      * ArenaFree call. We cannot free DSSKey and KEAKey separately */
  603.     pubk->u.fortezza.DSSKey.data=
  604. pubk->u.fortezza.KEAKey.data;
  605.     pubk->u.fortezza.DSSpriviledge.len = 
  606. pubk->u.fortezza.KEApriviledge.len;
  607.     pubk->u.fortezza.DSSpriviledge.data =
  608. pubk->u.fortezza.DSSpriviledge.data;
  609.     goto done;
  610. }
  611. /* DSS Version is next */
  612. pubk->u.fortezza.DSSversion = *rawptr++;
  613. if (*rawptr++ != 2) {
  614. return SECFailure;
  615. }
  616. /* DSSPrivilege (the string up to the first byte with the hi-bit on */
  617. clearptr = rawptr;
  618. while ((rawptr < end) && (*rawptr++ & 0x80));
  619. if (rawptr >= end) { return SECFailure; }
  620. pubk->u.fortezza.DSSpriviledge.len = rawptr - clearptr;
  621. pubk->u.fortezza.DSSpriviledge.data = 
  622. (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.DSSpriviledge.len);
  623. if (pubk->u.fortezza.DSSpriviledge.data == NULL) {
  624. return SECFailure;
  625. }
  626. PORT_Memcpy(pubk->u.fortezza.DSSpriviledge.data,clearptr,
  627. pubk->u.fortezza.DSSpriviledge.len);
  628. /* finally copy the DSS key. The next to bytes are the key length,
  629.  *  and the key follows */
  630. pubk->u.fortezza.DSSKey.len = (*rawptr << 8) | rawptr[1];
  631. rawptr += 2;
  632. if (rawptr+pubk->u.fortezza.DSSKey.len > end){ return SECFailure; }
  633. pubk->u.fortezza.DSSKey.data = 
  634. (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.DSSKey.len);
  635. if (pubk->u.fortezza.DSSKey.data == NULL) {
  636. return SECFailure;
  637. }
  638. PORT_Memcpy(pubk->u.fortezza.DSSKey.data,rawptr,
  639. pubk->u.fortezza.DSSKey.len);
  640. /* ok, now we decode the parameters */
  641. done:
  642.         return SECKEY_FortezzaDecodePQGtoOld(arena, pubk, params);
  643. }
  644. /* Function used to determine what kind of cert we are dealing with. */
  645. KeyType 
  646. CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) {
  647.     int tag;
  648.     KeyType keyType;
  649.     tag = SECOID_GetAlgorithmTag(&spki->algorithm);
  650.     switch (tag) {
  651.       case SEC_OID_X500_RSA_ENCRYPTION:
  652.       case SEC_OID_PKCS1_RSA_ENCRYPTION:
  653. keyType = rsaKey;
  654. break;
  655.       case SEC_OID_ANSIX9_DSA_SIGNATURE:
  656. keyType = dsaKey;
  657. break;
  658.       case SEC_OID_MISSI_KEA_DSS_OLD:
  659.       case SEC_OID_MISSI_KEA_DSS:
  660.       case SEC_OID_MISSI_DSS_OLD:
  661.       case SEC_OID_MISSI_DSS:  
  662. keyType = fortezzaKey;
  663. break;
  664.       case SEC_OID_MISSI_KEA:
  665.       case SEC_OID_MISSI_ALT_KEA:
  666. keyType = keaKey;
  667. break;
  668.       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
  669. keyType = dhKey;
  670.       default:
  671. keyType = nullKey;
  672.     }
  673.     return keyType;
  674. }
  675. static SECKEYPublicKey *
  676. seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
  677. {
  678.     SECKEYPublicKey *pubk;
  679.     SECItem os;
  680.     SECStatus rv;
  681.     PRArenaPool *arena;
  682.     SECOidTag tag;
  683.     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  684.     if (arena == NULL)
  685. return NULL;
  686.     pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
  687.     if (pubk == NULL) {
  688. PORT_FreeArena (arena, PR_FALSE);
  689. return NULL;
  690.     }
  691.     pubk->arena = arena;
  692.     pubk->pkcs11Slot = 0;
  693.     pubk->pkcs11ID = CK_INVALID_KEY;
  694.     /* Convert bit string length from bits to bytes */
  695.     os = spki->subjectPublicKey;
  696.     DER_ConvertBitString (&os);
  697.     tag = SECOID_GetAlgorithmTag(&spki->algorithm);
  698.     switch ( tag ) {
  699.       case SEC_OID_X500_RSA_ENCRYPTION:
  700.       case SEC_OID_PKCS1_RSA_ENCRYPTION:
  701. pubk->keyType = rsaKey;
  702. rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &os);
  703. if (rv == SECSuccess)
  704.     return pubk;
  705. break;
  706.       case SEC_OID_ANSIX9_DSA_SIGNATURE:
  707. pubk->keyType = dsaKey;
  708. rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &os);
  709. if (rv != SECSuccess) break;
  710.         rv = SECKEY_DSADecodePQG(arena, pubk,
  711.                                  &spki->algorithm.parameters); 
  712. if (rv == SECSuccess) return pubk;
  713. break;
  714.       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
  715. pubk->keyType = dhKey;
  716. rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &os);
  717. if (rv != SECSuccess) break;
  718.         rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
  719.                                  &spki->algorithm.parameters); 
  720. if (rv == SECSuccess) return pubk;
  721. break;
  722.       case SEC_OID_MISSI_KEA_DSS_OLD:
  723.       case SEC_OID_MISSI_KEA_DSS:
  724.       case SEC_OID_MISSI_DSS_OLD:
  725.       case SEC_OID_MISSI_DSS:
  726. pubk->keyType = fortezzaKey;
  727. rv = SECKEY_FortezzaDecodeCertKey(arena, pubk, &os,
  728.           &spki->algorithm.parameters);
  729. if (rv == SECSuccess)
  730.     return pubk;
  731. break;
  732.       case SEC_OID_MISSI_KEA:
  733. pubk->keyType = keaKey;
  734.         rv = SEC_ASN1DecodeItem(arena, pubk,
  735.                                 SECKEY_KEAPublicKeyTemplate, &os);
  736.         if (rv != SECSuccess) break;
  737.         rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_KEAParamsTemplate,
  738.                         &spki->algorithm.parameters);
  739. if (rv == SECSuccess)
  740.     return pubk;
  741.       break;
  742.       case SEC_OID_MISSI_ALT_KEA:
  743. pubk->keyType = keaKey;
  744.         rv = SECITEM_CopyItem(arena,&pubk->u.kea.publicValue,&os);
  745.         if (rv != SECSuccess) break;
  746.  
  747.         rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_KEAParamsTemplate,
  748.                         &spki->algorithm.parameters);
  749. if (rv == SECSuccess)
  750.     return pubk;
  751.       break;
  752.       default:
  753. rv = SECFailure;
  754. break;
  755.     }
  756.     SECKEY_DestroyPublicKey (pubk);
  757.     return NULL;
  758. }
  759. SECKEYPublicKey *
  760. CERT_ExtractPublicKey(CERTCertificate *cert)
  761. {
  762.     SECStatus rv;
  763.     rv = SECKEY_UpdateCertPQG(cert);
  764.     if (rv != SECSuccess) return NULL;
  765.     return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
  766. }
  767. /*
  768.  * Get the public key for the fortezza KMID. NOTE this requires the
  769.  * PQG paramters to be set. We probably should have a fortezza call that 
  770.  * just extracts the kmid for us directly so this function can work
  771.  * without having the whole cert chain
  772.  */
  773. SECKEYPublicKey *
  774. CERT_KMIDPublicKey(CERTCertificate *cert)
  775. {
  776.     return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
  777. }
  778. /* returns key strength in bytes (not bits) */
  779. unsigned
  780. SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
  781. {
  782.     unsigned char b0;
  783.     /* interpret modulus length as key strength... in
  784.      * fortezza that's the public key length */
  785.     switch (pubk->keyType) {
  786.     case rsaKey:
  787.      b0 = pubk->u.rsa.modulus.data[0];
  788.      return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
  789.     case dsaKey:
  790.      b0 = pubk->u.dsa.publicValue.data[0];
  791.      return b0 ? pubk->u.dsa.publicValue.len :
  792.     pubk->u.dsa.publicValue.len - 1;
  793.     case dhKey:
  794.      b0 = pubk->u.dh.publicValue.data[0];
  795.      return b0 ? pubk->u.dh.publicValue.len :
  796.     pubk->u.dh.publicValue.len - 1;
  797.     case fortezzaKey:
  798. return PR_MAX(pubk->u.fortezza.KEAKey.len, pubk->u.fortezza.DSSKey.len);
  799.     default:
  800. break;
  801.     }
  802.     return 0;
  803. }
  804. SECKEYPrivateKey *
  805. SECKEY_CopyPrivateKey(SECKEYPrivateKey *privk)
  806. {
  807.     SECKEYPrivateKey *copyk;
  808.     PRArenaPool *arena;
  809.     
  810.     if (privk == NULL) {
  811. return NULL;
  812.     }
  813.     
  814.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  815.     if (arena == NULL) {
  816. PORT_SetError (SEC_ERROR_NO_MEMORY);
  817. return NULL;
  818.     }
  819.     copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey));
  820.     if (copyk) {
  821. copyk->arena = arena;
  822. copyk->keyType = privk->keyType;
  823. /* copy the PKCS #11 parameters */
  824. copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
  825. /* if the key we're referencing was a temparary key we have just
  826.  * created, that we want to go away when we're through, we need
  827.  * to make a copy of it */
  828. if (privk->pkcs11IsTemp) {
  829.     copyk->pkcs11ID = 
  830. PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID);
  831.     if (copyk->pkcs11ID == CK_INVALID_KEY) goto fail;
  832. } else {
  833.     copyk->pkcs11ID = privk->pkcs11ID;
  834. }
  835. copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
  836. copyk->wincx = privk->wincx;
  837. return copyk;
  838.     } else {
  839. PORT_SetError (SEC_ERROR_NO_MEMORY);
  840.     }
  841. fail:
  842.     PORT_FreeArena (arena, PR_FALSE);
  843.     return NULL;
  844. }
  845. SECKEYPublicKey *
  846. SECKEY_CopyPublicKey(SECKEYPublicKey *pubk)
  847. {
  848.     SECKEYPublicKey *copyk;
  849.     PRArenaPool *arena;
  850.     
  851.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  852.     if (arena == NULL) {
  853. PORT_SetError (SEC_ERROR_NO_MEMORY);
  854. return NULL;
  855.     }
  856.     copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
  857.     if (copyk != NULL) {
  858. SECStatus rv = SECSuccess;
  859. copyk->arena = arena;
  860. copyk->keyType = pubk->keyType;
  861. copyk->pkcs11Slot = NULL; /* go get own reference */
  862. copyk->pkcs11ID = CK_INVALID_KEY;
  863. switch (pubk->keyType) {
  864.   case rsaKey:
  865.     rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
  866.   &pubk->u.rsa.modulus);
  867.     if (rv == SECSuccess) {
  868. rv = SECITEM_CopyItem (arena, &copyk->u.rsa.publicExponent,
  869.        &pubk->u.rsa.publicExponent);
  870. if (rv == SECSuccess)
  871.     return copyk;
  872.     }
  873.     break;
  874.   case dsaKey:
  875.     rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
  876.   &pubk->u.dsa.publicValue);
  877.     if (rv != SECSuccess) break;
  878.     rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
  879.   &pubk->u.dsa.params.prime);
  880.     if (rv != SECSuccess) break;
  881.     rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
  882.   &pubk->u.dsa.params.subPrime);
  883.     if (rv != SECSuccess) break;
  884.     rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
  885.   &pubk->u.dsa.params.base);
  886.     break;
  887.           case keaKey:
  888.             rv = SECITEM_CopyItem(arena, &copyk->u.kea.publicValue,
  889.                                   &pubk->u.kea.publicValue);
  890.             if (rv != SECSuccess) break;
  891.             rv = SECITEM_CopyItem(arena, &copyk->u.kea.params.hash,
  892.                                   &pubk->u.kea.params.hash);
  893.             break;
  894.   case fortezzaKey:
  895.     copyk->u.fortezza.KEAversion = pubk->u.fortezza.KEAversion;
  896.     copyk->u.fortezza.DSSversion = pubk->u.fortezza.DSSversion;
  897.     PORT_Memcpy(copyk->u.fortezza.KMID, pubk->u.fortezza.KMID,
  898. sizeof(pubk->u.fortezza.KMID));
  899.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.clearance, 
  900.   &pubk->u.fortezza.clearance);
  901.     if (rv != SECSuccess) break;
  902.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.KEApriviledge, 
  903. &pubk->u.fortezza.KEApriviledge);
  904.     if (rv != SECSuccess) break;
  905.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.DSSpriviledge, 
  906. &pubk->u.fortezza.DSSpriviledge);
  907.     if (rv != SECSuccess) break;
  908.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.KEAKey, 
  909. &pubk->u.fortezza.KEAKey);
  910.     if (rv != SECSuccess) break;
  911.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.DSSKey, 
  912. &pubk->u.fortezza.DSSKey);
  913.     if (rv != SECSuccess) break;
  914.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.prime, 
  915.   &pubk->u.fortezza.params.prime);
  916.     if (rv != SECSuccess) break;
  917.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.subPrime, 
  918. &pubk->u.fortezza.params.subPrime);
  919.     if (rv != SECSuccess) break;
  920.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.base, 
  921. &pubk->u.fortezza.params.base);
  922.             if (rv != SECSuccess) break;
  923.             rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.prime, 
  924.   &pubk->u.fortezza.keaParams.prime);
  925.     if (rv != SECSuccess) break;
  926.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.subPrime, 
  927. &pubk->u.fortezza.keaParams.subPrime);
  928.     if (rv != SECSuccess) break;
  929.     rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.base, 
  930. &pubk->u.fortezza.keaParams.base);
  931.     break;
  932.   case dhKey:
  933.             rv = SECITEM_CopyItem(arena,&copyk->u.dh.prime,&pubk->u.dh.prime);
  934.     if (rv != SECSuccess) break;
  935.     rv = SECITEM_CopyItem(arena,&copyk->u.dh.base,&pubk->u.dh.base);
  936.     if (rv != SECSuccess) break;
  937.     rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue, 
  938. &pubk->u.dh.publicValue);
  939.     break;
  940.   case nullKey:
  941.     return copyk;
  942.   default:
  943.     rv = SECFailure;
  944.     break;
  945. }
  946. if (rv == SECSuccess)
  947.     return copyk;
  948. SECKEY_DestroyPublicKey (copyk);
  949.     } else {
  950. PORT_SetError (SEC_ERROR_NO_MEMORY);
  951.     }
  952.     PORT_FreeArena (arena, PR_FALSE);
  953.     return NULL;
  954. }
  955. SECKEYPublicKey *
  956. SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
  957. {
  958.     SECKEYPublicKey *pubk;
  959.     PRArenaPool *arena;
  960.     CERTCertificate *cert;
  961.     SECStatus rv;
  962.     /*
  963.      * First try to look up the cert.
  964.      */
  965.     cert = PK11_GetCertFromPrivateKey(privk);
  966.     if (cert) {
  967. pubk = CERT_ExtractPublicKey(cert);
  968. CERT_DestroyCertificate(cert);
  969. return pubk;
  970.     }
  971.     /* couldn't find the cert, build pub key by hand */
  972.     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  973.     if (arena == NULL) {
  974. PORT_SetError (SEC_ERROR_NO_MEMORY);
  975. return NULL;
  976.     }
  977.     pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
  978.    sizeof (SECKEYPublicKey));
  979.     if (pubk == NULL) {
  980. PORT_FreeArena(arena,PR_FALSE);
  981. return NULL;
  982.     }
  983.     pubk->keyType = privk->keyType;
  984.     pubk->pkcs11Slot = NULL;
  985.     pubk->pkcs11ID = CK_INVALID_KEY;
  986.     pubk->arena = arena;
  987.     /*
  988.      * fortezza is at the head of this switch, since we don't want to
  989.      * allocate an arena... CERT_ExtractPublicKey will to that for us.
  990.      */
  991.     switch(privk->keyType) {
  992.       case fortezzaKey:
  993.       case nullKey:
  994.       case dhKey:
  995.       case dsaKey:
  996. /* Nothing to query, if the cert isn't there, we're done -- no way
  997.  * to get the public key */
  998. break;
  999.       case rsaKey:
  1000. rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
  1001. CKA_MODULUS,arena,&pubk->u.rsa.modulus);
  1002. if (rv != SECSuccess)  break;
  1003. rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
  1004. CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent);
  1005. if (rv != SECSuccess)  break;
  1006. return pubk;
  1007. break;
  1008.     default:
  1009. break;
  1010.     }
  1011.     PORT_FreeArena (arena, PR_FALSE);
  1012.     return NULL;
  1013. }
  1014. CERTSubjectPublicKeyInfo *
  1015. SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
  1016. {
  1017.     CERTSubjectPublicKeyInfo *spki;
  1018.     PRArenaPool *arena;
  1019.     SECItem params = { siBuffer, NULL, 0 };
  1020.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1021.     if (arena == NULL) {
  1022. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1023. return NULL;
  1024.     }
  1025.     spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki));
  1026.     if (spki != NULL) {
  1027. SECStatus rv;
  1028. SECItem *rv_item;
  1029. spki->arena = arena;
  1030. switch(pubk->keyType) {
  1031.   case rsaKey:
  1032.     rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1033.      SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
  1034.     if (rv == SECSuccess) {
  1035. /*
  1036.  * DER encode the public key into the subjectPublicKeyInfo.
  1037.  */
  1038. rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
  1039.      pubk, SECKEY_RSAPublicKeyTemplate);
  1040. if (rv_item != NULL) {
  1041.     /*
  1042.      * The stored value is supposed to be a BIT_STRING,
  1043.      * so convert the length.
  1044.      */
  1045.     spki->subjectPublicKey.len <<= 3;
  1046.     /*
  1047.      * We got a good one; return it.
  1048.      */
  1049.     return spki;
  1050. }
  1051.     }
  1052.     break;
  1053.   case dsaKey:
  1054.     /* DER encode the params. */
  1055.     rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
  1056.  SECKEY_PQGParamsTemplate);
  1057.     if (rv_item != NULL) {
  1058. rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1059.    SEC_OID_ANSIX9_DSA_SIGNATURE,
  1060.    &params);
  1061. if (rv == SECSuccess) {
  1062.     /*
  1063.      * DER encode the public key into the subjectPublicKeyInfo.
  1064.      */
  1065.     rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
  1066.  pubk,
  1067.  SECKEY_DSAPublicKeyTemplate);
  1068.     if (rv_item != NULL) {
  1069. /*
  1070.  * The stored value is supposed to be a BIT_STRING,
  1071.  * so convert the length.
  1072.  */
  1073. spki->subjectPublicKey.len <<= 3;
  1074. /*
  1075.  * We got a good one; return it.
  1076.  */
  1077. return spki;
  1078.     }
  1079. }
  1080.     }
  1081.     SECITEM_FreeItem(&params, PR_FALSE);
  1082.     break;
  1083.   case keaKey:
  1084.   case dhKey: /* later... */
  1085.   break;  
  1086.   case fortezzaKey:
  1087. #ifdef notdef
  1088.     /* encode the DSS parameters (PQG) */
  1089.     rv = FortezzaBuildParams(&params,pubk);
  1090.     if (rv != SECSuccess) break;
  1091.     /* set the algorithm */
  1092.     rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1093.        SEC_OID_MISSI_KEA_DSS, &params);
  1094.     PORT_Free(params.data);
  1095.     if (rv == SECSuccess) {
  1096. /*
  1097.  * Encode the public key into the subjectPublicKeyInfo.
  1098.  * Fortezza key material is not standard DER
  1099.  */
  1100. rv = FortezzaEncodeCertKey(arena,&spki->subjectPublicKey,pubk);
  1101. if (rv == SECSuccess) {
  1102.     /*
  1103.      * The stored value is supposed to be a BIT_STRING,
  1104.      * so convert the length.
  1105.      */
  1106.     spki->subjectPublicKey.len <<= 3;
  1107.     /*
  1108.      * We got a good one; return it.
  1109.      */
  1110.     return spki;
  1111. }
  1112.     }
  1113. #endif
  1114.     break;
  1115.   default:
  1116.     break;
  1117. }
  1118.     } else {
  1119. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1120.     }
  1121.     PORT_FreeArena(arena, PR_FALSE);
  1122.     return NULL;
  1123. }
  1124. void
  1125. SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
  1126. {
  1127.     if (spki && spki->arena) {
  1128. PORT_FreeArena(spki->arena, PR_FALSE);
  1129.     }
  1130. }
  1131. /*
  1132.  * this only works for RSA keys... need to do something
  1133.  * similiar to CERT_ExtractPublicKey for other key times.
  1134.  */
  1135. SECKEYPublicKey *
  1136. SECKEY_DecodeDERPublicKey(SECItem *pubkder)
  1137. {
  1138.     PRArenaPool *arena;
  1139.     SECKEYPublicKey *pubk;
  1140.     SECStatus rv;
  1141.     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  1142.     if (arena == NULL) {
  1143. PORT_SetError (SEC_ERROR_NO_MEMORY);
  1144. return NULL;
  1145.     }
  1146.     pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
  1147.     if (pubk != NULL) {
  1148. pubk->arena = arena;
  1149. pubk->pkcs11Slot = NULL;
  1150. pubk->pkcs11ID = 0;
  1151. rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate,
  1152. pubkder);
  1153. if (rv == SECSuccess)
  1154.     return pubk;
  1155. SECKEY_DestroyPublicKey (pubk);
  1156.     } else {
  1157. PORT_SetError (SEC_ERROR_NO_MEMORY);
  1158.     }
  1159.     PORT_FreeArena (arena, PR_FALSE);
  1160.     return NULL;
  1161. }
  1162. /*
  1163.  * Decode a base64 ascii encoded DER encoded public key.
  1164.  */
  1165. SECKEYPublicKey *
  1166. SECKEY_ConvertAndDecodePublicKey(char *pubkstr)
  1167. {
  1168.     SECKEYPublicKey *pubk;
  1169.     SECStatus rv;
  1170.     SECItem der;
  1171.     rv = ATOB_ConvertAsciiToItem (&der, pubkstr);
  1172.     if (rv != SECSuccess)
  1173. return NULL;
  1174.     pubk = SECKEY_DecodeDERPublicKey (&der);
  1175.     PORT_Free (der.data);
  1176.     return pubk;
  1177. }
  1178. CERTSubjectPublicKeyInfo *
  1179. SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider)
  1180. {
  1181.     PRArenaPool *arena;
  1182.     CERTSubjectPublicKeyInfo *spki;
  1183.     SECStatus rv;
  1184.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1185.     if (arena == NULL) {
  1186. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1187. return NULL;
  1188.     }
  1189.     spki = (CERTSubjectPublicKeyInfo *)
  1190. PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo));
  1191.     if (spki != NULL) {
  1192. spki->arena = arena;
  1193. rv = SEC_ASN1DecodeItem(arena,spki,
  1194. CERT_SubjectPublicKeyInfoTemplate,spkider);
  1195. if (rv == SECSuccess)
  1196.     return spki;
  1197. SECKEY_DestroySubjectPublicKeyInfo(spki);
  1198.     } else {
  1199. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1200.     }
  1201.     PORT_FreeArena(arena, PR_FALSE);
  1202.     return NULL;
  1203. }
  1204. /*
  1205.  * Decode a base64 ascii encoded DER encoded subject public key info.
  1206.  */
  1207. CERTSubjectPublicKeyInfo *
  1208. SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(char *spkistr)
  1209. {
  1210.     CERTSubjectPublicKeyInfo *spki;
  1211.     SECStatus rv;
  1212.     SECItem der;
  1213.     rv = ATOB_ConvertAsciiToItem(&der, spkistr);
  1214.     if (rv != SECSuccess)
  1215. return NULL;
  1216.     spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
  1217.     PORT_Free(der.data);
  1218.     return spki;
  1219. }
  1220. /*
  1221.  * Decode a base64 ascii encoded DER encoded public key and challenge
  1222.  * Verify digital signature and make sure challenge matches
  1223.  */
  1224. CERTSubjectPublicKeyInfo *
  1225. SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
  1226. void *wincx)
  1227. {
  1228.     CERTSubjectPublicKeyInfo *spki = NULL;
  1229.     CERTPublicKeyAndChallenge pkac;
  1230.     SECStatus rv;
  1231.     SECItem signedItem;
  1232.     PRArenaPool *arena = NULL;
  1233.     CERTSignedData sd;
  1234.     SECItem sig;
  1235.     SECKEYPublicKey *pubKey = NULL;
  1236.     int len;
  1237.     
  1238.     signedItem.data = NULL;
  1239.     
  1240.     /* convert the base64 encoded data to binary */
  1241.     rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
  1242.     if (rv != SECSuccess) {
  1243. goto loser;
  1244.     }
  1245.     /* create an arena */
  1246.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1247.     if (arena == NULL) {
  1248. goto loser;
  1249.     }
  1250.     /* decode the outer wrapping of signed data */
  1251.     PORT_Memset(&sd, 0, sizeof(CERTSignedData));
  1252.     rv = SEC_ASN1DecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem );
  1253.     if ( rv ) {
  1254. goto loser;
  1255.     }
  1256.     /* decode the public key and challenge wrapper */
  1257.     PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
  1258.     rv = SEC_ASN1DecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate, 
  1259.     &sd.data);
  1260.     if ( rv ) {
  1261. goto loser;
  1262.     }
  1263.     /* decode the subject public key info */
  1264.     spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
  1265.     if ( spki == NULL ) {
  1266. goto loser;
  1267.     }
  1268.     
  1269.     /* get the public key */
  1270.     pubKey = seckey_ExtractPublicKey(spki);
  1271.     if ( pubKey == NULL ) {
  1272. goto loser;
  1273.     }
  1274.     /* check the signature */
  1275.     sig = sd.signature;
  1276.     DER_ConvertBitString(&sig);
  1277.     rv = VFY_VerifyData(sd.data.data, sd.data.len, pubKey, &sig,
  1278. SECOID_GetAlgorithmTag(&(sd.signatureAlgorithm)), wincx);
  1279.     if ( rv != SECSuccess ) {
  1280. goto loser;
  1281.     }
  1282.     
  1283.     /* check the challenge */
  1284.     if ( challenge ) {
  1285. len = PORT_Strlen(challenge);
  1286. /* length is right */
  1287. if ( len != pkac.challenge.len ) {
  1288.     goto loser;
  1289. }
  1290. /* actual data is right */
  1291. if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) {
  1292.     goto loser;
  1293. }
  1294.     }
  1295.     goto done;
  1296. loser:
  1297.     /* make sure that we return null if we got an error */
  1298.     if ( spki ) {
  1299. SECKEY_DestroySubjectPublicKeyInfo(spki);
  1300.     }
  1301.     spki = NULL;
  1302.     
  1303. done:
  1304.     if ( signedItem.data ) {
  1305. PORT_Free(signedItem.data);
  1306.     }
  1307.     if ( arena ) {
  1308. PORT_FreeArena(arena, PR_FALSE);
  1309.     }
  1310.     if ( pubKey ) {
  1311. SECKEY_DestroyPublicKey(pubKey);
  1312.     }
  1313.     
  1314.     return spki;
  1315. }
  1316. void
  1317. SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
  1318.      PRBool freeit)
  1319. {
  1320.     PRArenaPool *poolp;
  1321.     if(pvk != NULL) {
  1322. if(pvk->arena) {
  1323.     poolp = pvk->arena;
  1324.     /* zero structure since PORT_FreeArena does not support
  1325.      * this yet.
  1326.      */
  1327.     PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
  1328.     PORT_Memset((char *)pvk, 0, sizeof(*pvk));
  1329.     if(freeit == PR_TRUE) {
  1330. PORT_FreeArena(poolp, PR_TRUE);
  1331.     } else {
  1332. pvk->arena = poolp;
  1333.     }
  1334. } else {
  1335.     SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
  1336.     SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
  1337.     SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
  1338.     PORT_Memset((char *)pvk, 0, sizeof(pvk));
  1339.     if(freeit == PR_TRUE) {
  1340. PORT_Free(pvk);
  1341.     }
  1342. }
  1343.     }
  1344. }
  1345. void
  1346. SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
  1347.       PRBool freeit)
  1348. {
  1349.     PRArenaPool *poolp;
  1350.     if(epki != NULL) {
  1351. if(epki->arena) {
  1352.     poolp = epki->arena;
  1353.     /* zero structure since PORT_FreeArena does not support
  1354.      * this yet.
  1355.      */
  1356.     PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
  1357.     PORT_Memset((char *)epki, 0, sizeof(*epki));
  1358.     if(freeit == PR_TRUE) {
  1359. PORT_FreeArena(poolp, PR_TRUE);
  1360.     } else {
  1361. epki->arena = poolp;
  1362.     }
  1363. } else {
  1364.     SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
  1365.     SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
  1366.     PORT_Memset((char *)epki, 0, sizeof(epki));
  1367.     if(freeit == PR_TRUE) {
  1368. PORT_Free(epki);
  1369.     }
  1370. }
  1371.     }
  1372. }
  1373. SECStatus
  1374. SECKEY_CopyPrivateKeyInfo(PRArenaPool *poolp,
  1375.   SECKEYPrivateKeyInfo *to,
  1376.   SECKEYPrivateKeyInfo *from)
  1377. {
  1378.     SECStatus rv = SECFailure;
  1379.     if((to == NULL) || (from == NULL)) {
  1380. return SECFailure;
  1381.     }
  1382.     rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
  1383.     if(rv != SECSuccess) {
  1384. return SECFailure;
  1385.     }
  1386.     rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
  1387.     if(rv != SECSuccess) {
  1388. return SECFailure;
  1389.     }
  1390.     rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
  1391.     return rv;
  1392. }
  1393. SECStatus
  1394. SECKEY_CopyEncryptedPrivateKeyInfo(PRArenaPool *poolp, 
  1395.    SECKEYEncryptedPrivateKeyInfo *to,
  1396.    SECKEYEncryptedPrivateKeyInfo *from)
  1397. {
  1398.     SECStatus rv = SECFailure;
  1399.     if((to == NULL) || (from == NULL)) {
  1400. return SECFailure;
  1401.     }
  1402.     rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
  1403.     if(rv != SECSuccess) {
  1404. return SECFailure;
  1405.     }
  1406.     rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
  1407.     return rv;
  1408. }
  1409. KeyType
  1410. SECKEY_GetPrivateKeyType(SECKEYPrivateKey *privKey)
  1411. {
  1412.    return privKey->keyType;
  1413. }
  1414. KeyType
  1415. SECKEY_GetPublicKeyType(SECKEYPublicKey *pubKey)
  1416. {
  1417.    return pubKey->keyType;
  1418. }