Back to index

lightning-sunbird  0.9+nobinonly
cmspubkey.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * CMS public key crypto
00039  *
00040  * $Id: cmspubkey.c,v 1.7 2004/04/25 15:03:16 gerv%gerv.net Exp $
00041  */
00042 
00043 #include "cmslocal.h"
00044 
00045 #include "cert.h"
00046 #include "key.h"
00047 #include "secasn1.h"
00048 #include "secitem.h"
00049 #include "secoid.h"
00050 #include "pk11func.h"
00051 #include "secerr.h"
00052 
00053 /* ====== RSA ======================================================================= */
00054 
00055 /*
00056  * NSS_CMSUtil_EncryptSymKey_RSA - wrap a symmetric key with RSA
00057  *
00058  * this function takes a symmetric key and encrypts it using an RSA public key
00059  * according to PKCS#1 and RFC2633 (S/MIME)
00060  */
00061 SECStatus
00062 NSS_CMSUtil_EncryptSymKey_RSA(PLArenaPool *poolp, CERTCertificate *cert, 
00063                               PK11SymKey *bulkkey,
00064                               SECItem *encKey)
00065 {
00066     SECStatus rv;
00067     SECKEYPublicKey *publickey;
00068 
00069     publickey = CERT_ExtractPublicKey(cert);
00070     if (publickey == NULL)
00071        return SECFailure;
00072 
00073     rv = NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp, publickey, bulkkey, encKey);
00074     SECKEY_DestroyPublicKey(publickey);
00075     return rv;
00076 }
00077 
00078 SECStatus
00079 NSS_CMSUtil_EncryptSymKey_RSAPubKey(PLArenaPool *poolp, 
00080                                     SECKEYPublicKey *publickey, 
00081                                     PK11SymKey *bulkkey, SECItem *encKey)
00082 {
00083     SECStatus rv;
00084     int data_len;
00085     KeyType keyType;
00086     void *mark = NULL;
00087 
00088 
00089     mark = PORT_ArenaMark(poolp);
00090     if (!mark)
00091        goto loser;
00092 
00093     /* sanity check */
00094     keyType = SECKEY_GetPublicKeyType(publickey);
00095     PORT_Assert(keyType == rsaKey);
00096     if (keyType != rsaKey) {
00097        goto loser;
00098     }
00099     /* allocate memory for the encrypted key */
00100     data_len = SECKEY_PublicKeyStrength(publickey);     /* block size (assumed to be > keylen) */
00101     encKey->data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len);
00102     encKey->len = data_len;
00103     if (encKey->data == NULL)
00104        goto loser;
00105 
00106     /* encrypt the key now */
00107     rv = PK11_PubWrapSymKey(PK11_AlgtagToMechanism(SEC_OID_PKCS1_RSA_ENCRYPTION),
00108                             publickey, bulkkey, encKey);
00109 
00110     if (rv != SECSuccess)
00111        goto loser;
00112 
00113     PORT_ArenaUnmark(poolp, mark);
00114     return SECSuccess;
00115 
00116 loser:
00117     if (mark) {
00118        PORT_ArenaRelease(poolp, mark);
00119     }
00120     return SECFailure;
00121 }
00122 
00123 /*
00124  * NSS_CMSUtil_DecryptSymKey_RSA - unwrap a RSA-wrapped symmetric key
00125  *
00126  * this function takes an RSA-wrapped symmetric key and unwraps it, returning a symmetric
00127  * key handle. Please note that the actual unwrapped key data may not be allowed to leave
00128  * a hardware token...
00129  */
00130 PK11SymKey *
00131 NSS_CMSUtil_DecryptSymKey_RSA(SECKEYPrivateKey *privkey, SECItem *encKey, SECOidTag bulkalgtag)
00132 {
00133     /* that's easy */
00134     CK_MECHANISM_TYPE target;
00135     PORT_Assert(bulkalgtag != SEC_OID_UNKNOWN);
00136     target = PK11_AlgtagToMechanism(bulkalgtag);
00137     if (bulkalgtag == SEC_OID_UNKNOWN || target == CKM_INVALID_MECHANISM) {
00138        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
00139        return NULL;
00140     }
00141     return PK11_PubUnwrapSymKey(privkey, encKey, target, CKA_DECRYPT, 0);
00142 }
00143 
00144 /* ====== MISSI (Fortezza) ========================================================== */
00145 
00146 extern const SEC_ASN1Template NSS_SMIMEKEAParamTemplateAllParams[];
00147 
00148 SECStatus
00149 NSS_CMSUtil_EncryptSymKey_MISSI(PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *bulkkey,
00150                      SECOidTag symalgtag, SECItem *encKey, SECItem **pparams, void *pwfn_arg)
00151 {
00152     SECOidTag certalgtag;   /* the certificate's encryption algorithm */
00153     SECOidTag encalgtag;    /* the algorithm used for key exchange/agreement */
00154     SECStatus rv = SECFailure;
00155     SECItem *params = NULL;
00156     SECStatus err;
00157     PK11SymKey *tek;
00158     CERTCertificate *ourCert;
00159     SECKEYPublicKey *ourPubKey, *publickey = NULL;
00160     SECKEYPrivateKey *ourPrivKey = NULL;
00161     NSSCMSKEATemplateSelector whichKEA = NSSCMSKEAInvalid;
00162     NSSCMSSMIMEKEAParameters keaParams;
00163     PLArenaPool *arena = NULL;
00164     extern const SEC_ASN1Template *nss_cms_get_kea_template(NSSCMSKEATemplateSelector whichTemplate);
00165 
00166     /* Clear keaParams, since cleanup code checks the lengths */
00167     (void) memset(&keaParams, 0, sizeof(keaParams));
00168 
00169     certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
00170     PORT_Assert(certalgtag == SEC_OID_MISSI_KEA_DSS_OLD ||
00171               certalgtag == SEC_OID_MISSI_KEA_DSS ||
00172               certalgtag == SEC_OID_MISSI_KEA);
00173 
00174 #define SMIME_FORTEZZA_RA_LENGTH 128
00175 #define SMIME_FORTEZZA_IV_LENGTH 24
00176 #define SMIME_FORTEZZA_MAX_KEY_SIZE 256
00177 
00178     /* We really want to show our KEA tag as the key exchange algorithm tag. */
00179     encalgtag = SEC_OID_NETSCAPE_SMIME_KEA;
00180 
00181     /* Get the public key of the recipient. */
00182     publickey = CERT_ExtractPublicKey(cert);
00183     if (publickey == NULL) goto loser;
00184 
00185     /* Find our own cert, and extract its keys. */
00186     ourCert = PK11_FindBestKEAMatch(cert, pwfn_arg);
00187     if (ourCert == NULL) goto loser;
00188 
00189     arena = PORT_NewArena(1024);
00190     if (arena == NULL)
00191        goto loser;
00192 
00193     ourPubKey = CERT_ExtractPublicKey(ourCert);
00194     if (ourPubKey == NULL) {
00195        CERT_DestroyCertificate(ourCert);
00196        goto loser;
00197     }
00198 
00199     /* While we're here, copy the public key into the outgoing
00200      * KEA parameters. */
00201     SECITEM_CopyItem(arena, &(keaParams.originatorKEAKey), &(ourPubKey->u.fortezza.KEAKey));
00202     SECKEY_DestroyPublicKey(ourPubKey);
00203     ourPubKey = NULL;
00204 
00205     /* Extract our private key in order to derive the KEA key. */
00206     ourPrivKey = PK11_FindKeyByAnyCert(ourCert, pwfn_arg);
00207     CERT_DestroyCertificate(ourCert); /* we're done with this */
00208     if (!ourPrivKey)
00209        goto loser;
00210 
00211     /* Prepare raItem with 128 bytes (filled with zeros). */
00212     keaParams.originatorRA.data = (unsigned char *)PORT_ArenaAlloc(arena,SMIME_FORTEZZA_RA_LENGTH);
00213     keaParams.originatorRA.len = SMIME_FORTEZZA_RA_LENGTH;
00214 
00215     /* Generate the TEK (token exchange key) which we use
00216      * to wrap the bulk encryption key. (keaparams.originatorRA) will be
00217      * filled with a random seed which we need to send to
00218      * the recipient. (user keying material in RFC2630/DSA speak) */
00219     tek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE,
00220                       &keaParams.originatorRA, NULL,
00221                       CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP,
00222                       CKA_WRAP, 0,  pwfn_arg);
00223 
00224     SECKEY_DestroyPublicKey(publickey);
00225     SECKEY_DestroyPrivateKey(ourPrivKey);
00226     publickey = NULL;
00227     ourPrivKey = NULL;
00228     
00229     if (!tek)
00230        goto loser;
00231 
00232     /* allocate space for the wrapped key data */
00233     encKey->data = (unsigned char *)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE);
00234     encKey->len = SMIME_FORTEZZA_MAX_KEY_SIZE;
00235 
00236     if (encKey->data == NULL) {
00237        PK11_FreeSymKey(tek);
00238        goto loser;
00239     }
00240 
00241     /* Wrap the bulk key. What we do with the resulting data
00242        depends on whether we're using Skipjack to wrap the key. */
00243     switch (PK11_AlgtagToMechanism(symalgtag)) {
00244     case CKM_SKIPJACK_CBC64:
00245     case CKM_SKIPJACK_ECB64:
00246     case CKM_SKIPJACK_OFB64:
00247     case CKM_SKIPJACK_CFB64:
00248     case CKM_SKIPJACK_CFB32:
00249     case CKM_SKIPJACK_CFB16:
00250     case CKM_SKIPJACK_CFB8:
00251        /* SKIPJACK, we use the wrap mechanism because we can do it on the hardware */
00252        err = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, tek, bulkkey, encKey);
00253        whichKEA = NSSCMSKEAUsesSkipjack;
00254        break;
00255     default:
00256        /* Not SKIPJACK, we encrypt the raw key data */
00257        keaParams.nonSkipjackIV.data = 
00258          (unsigned char *)PORT_ArenaAlloc(arena, SMIME_FORTEZZA_IV_LENGTH);
00259        keaParams.nonSkipjackIV.len = SMIME_FORTEZZA_IV_LENGTH;
00260        err = PK11_WrapSymKey(CKM_SKIPJACK_CBC64, &keaParams.nonSkipjackIV, tek, bulkkey, encKey);
00261        if (err != SECSuccess)
00262            goto loser;
00263 
00264        if (encKey->len != PK11_GetKeyLength(bulkkey)) {
00265            /* The size of the encrypted key is not the same as
00266               that of the original bulk key, presumably due to
00267               padding. Encode and store the real size of the
00268               bulk key. */
00269            if (SEC_ASN1EncodeInteger(arena, &keaParams.bulkKeySize, PK11_GetKeyLength(bulkkey)) == NULL)
00270               err = (SECStatus)PORT_GetError();
00271            else
00272               /* use full template for encoding */
00273               whichKEA = NSSCMSKEAUsesNonSkipjackWithPaddedEncKey;
00274        }
00275        else
00276            /* enc key length == bulk key length */
00277            whichKEA = NSSCMSKEAUsesNonSkipjack; 
00278        break;
00279     }
00280 
00281     PK11_FreeSymKey(tek);
00282 
00283     if (err != SECSuccess)
00284        goto loser;
00285 
00286     PORT_Assert(whichKEA != NSSCMSKEAInvalid);
00287 
00288     /* Encode the KEA parameters into the recipient info. */
00289     params = SEC_ASN1EncodeItem(poolp, NULL, &keaParams, nss_cms_get_kea_template(whichKEA));
00290     if (params == NULL)
00291        goto loser;
00292 
00293     /* pass back the algorithm params */
00294     *pparams = params;
00295 
00296     rv = SECSuccess;
00297 
00298 loser:
00299     if (arena)
00300        PORT_FreeArena(arena, PR_FALSE);
00301     if (publickey)
00302         SECKEY_DestroyPublicKey(publickey);
00303     if (ourPrivKey)
00304         SECKEY_DestroyPrivateKey(ourPrivKey);
00305     return rv;
00306 }
00307 
00308 PK11SymKey *
00309 NSS_CMSUtil_DecryptSymKey_MISSI(SECKEYPrivateKey *privkey, SECItem *encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg)
00310 {
00311     /* fortezza: do a key exchange */
00312     SECStatus err;
00313     CK_MECHANISM_TYPE bulkType;
00314     PK11SymKey *tek;
00315     SECKEYPublicKey *originatorPubKey;
00316     NSSCMSSMIMEKEAParameters keaParams;
00317     PK11SymKey *bulkkey;
00318     int bulkLength;
00319 
00320     (void) memset(&keaParams, 0, sizeof(keaParams));
00321 
00322     /* NOTE: this uses the SMIME v2 recipientinfo for compatibility.
00323        All additional KEA parameters are DER-encoded in the encryption algorithm parameters */
00324 
00325     /* Decode the KEA algorithm parameters. */
00326     err = SEC_ASN1DecodeItem(NULL, &keaParams, NSS_SMIMEKEAParamTemplateAllParams,
00327                           &(keyEncAlg->parameters));
00328     if (err != SECSuccess)
00329        goto loser;
00330 
00331     /* get originator's public key */
00332    originatorPubKey = PK11_MakeKEAPubKey(keaParams.originatorKEAKey.data,
00333                         keaParams.originatorKEAKey.len);
00334    if (originatorPubKey == NULL)
00335          goto loser;
00336     
00337    /* Generate the TEK (token exchange key) which we use to unwrap the bulk encryption key.
00338       The Derive function generates a shared secret and combines it with the originatorRA
00339       data to come up with an unique session key */
00340    tek = PK11_PubDerive(privkey, originatorPubKey, PR_FALSE,
00341                       &keaParams.originatorRA, NULL,
00342                       CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP,
00343                       CKA_WRAP, 0, pwfn_arg);
00344    SECKEY_DestroyPublicKey(originatorPubKey);    /* not needed anymore */
00345    if (tek == NULL)
00346        goto loser;
00347     
00348     /* Now that we have the TEK, unwrap the bulk key
00349        with which to decrypt the message. We have to
00350        do one of two different things depending on 
00351        whether Skipjack was used for *bulk* encryption 
00352        of the message. */
00353     bulkType = PK11_AlgtagToMechanism(bulkalgtag);
00354     switch (bulkType) {
00355     case CKM_SKIPJACK_CBC64:
00356     case CKM_SKIPJACK_ECB64:
00357     case CKM_SKIPJACK_OFB64:
00358     case CKM_SKIPJACK_CFB64:
00359     case CKM_SKIPJACK_CFB32:
00360     case CKM_SKIPJACK_CFB16:
00361     case CKM_SKIPJACK_CFB8:
00362        /* Skipjack is being used as the bulk encryption algorithm.*/
00363        /* Unwrap the bulk key. */
00364        bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL,
00365                                 encKey, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0);
00366        break;
00367     default:
00368        /* Skipjack was not used for bulk encryption of this
00369           message. Use Skipjack CBC64, with the nonSkipjackIV
00370           part of the KEA key parameters, to decrypt 
00371           the bulk key. If the optional parameter bulkKeySize is present,
00372           bulk key size is different than the encrypted key size */
00373        if (keaParams.bulkKeySize.len > 0) {
00374            err = SEC_ASN1DecodeItem(NULL, &bulkLength,
00375                                  SEC_ASN1_GET(SEC_IntegerTemplate),
00376                                  &keaParams.bulkKeySize);
00377            if (err != SECSuccess)
00378               goto loser;
00379        }
00380        
00381        bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_CBC64, &keaParams.nonSkipjackIV, 
00382                                 encKey, bulkType, CKA_DECRYPT, bulkLength);
00383        break;
00384     }
00385     return bulkkey;
00386 loser:
00387     return NULL;
00388 }
00389 
00390 /* ====== ESDH (Ephemeral-Static Diffie-Hellman) ==================================== */
00391 
00392 SECStatus
00393 NSS_CMSUtil_EncryptSymKey_ESDH(PLArenaPool *poolp, CERTCertificate *cert, PK11SymKey *key,
00394                      SECItem *encKey, SECItem **ukm, SECAlgorithmID *keyEncAlg,
00395                      SECItem *pubKey)
00396 {
00397 #if 0 /* not yet done */
00398     SECOidTag certalgtag;   /* the certificate's encryption algorithm */
00399     SECOidTag encalgtag;    /* the algorithm used for key exchange/agreement */
00400     SECStatus rv;
00401     SECItem *params = NULL;
00402     int data_len;
00403     SECStatus err;
00404     PK11SymKey *tek;
00405     CERTCertificate *ourCert;
00406     SECKEYPublicKey *ourPubKey;
00407     NSSCMSKEATemplateSelector whichKEA = NSSCMSKEAInvalid;
00408 
00409     certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
00410     PORT_Assert(certalgtag == SEC_OID_X942_DIFFIE_HELMAN_KEY);
00411 
00412     /* We really want to show our KEA tag as the key exchange algorithm tag. */
00413     encalgtag = SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN;
00414 
00415     /* Get the public key of the recipient. */
00416     publickey = CERT_ExtractPublicKey(cert);
00417     if (publickey == NULL) goto loser;
00418 
00419     /* XXXX generate a DH key pair on a PKCS11 module (XXX which parameters?) */
00420     /* XXXX */ourCert = PK11_FindBestKEAMatch(cert, wincx);
00421     if (ourCert == NULL) goto loser;
00422 
00423     arena = PORT_NewArena(1024);
00424     if (arena == NULL) goto loser;
00425 
00426     /* While we're here, extract the key pair's public key data and copy it into */
00427     /* the outgoing parameters. */
00428     /* XXXX */ourPubKey = CERT_ExtractPublicKey(ourCert);
00429     if (ourPubKey == NULL)
00430     {
00431        goto loser;
00432     }
00433     SECITEM_CopyItem(arena, pubKey, /* XXX */&(ourPubKey->u.fortezza.KEAKey));
00434     SECKEY_DestroyPublicKey(ourPubKey); /* we only need the private key from now on */
00435     ourPubKey = NULL;
00436 
00437     /* Extract our private key in order to derive the KEA key. */
00438     ourPrivKey = PK11_FindKeyByAnyCert(ourCert,wincx);
00439     CERT_DestroyCertificate(ourCert); /* we're done with this */
00440     if (!ourPrivKey) goto loser;
00441 
00442     /* If ukm desired, prepare it - allocate enough space (filled with zeros). */
00443     if (ukm) {
00444        ukm->data = (unsigned char*)PORT_ArenaZAlloc(arena,/* XXXX */);
00445        ukm->len = /* XXXX */;
00446     }
00447 
00448     /* Generate the KEK (key exchange key) according to RFC2631 which we use
00449      * to wrap the bulk encryption key. */
00450     kek = PK11_PubDerive(ourPrivKey, publickey, PR_TRUE,
00451                       ukm, NULL,
00452                       /* XXXX */CKM_KEA_KEY_DERIVE, /* XXXX */CKM_SKIPJACK_WRAP,
00453                       CKA_WRAP, 0, wincx);
00454 
00455     SECKEY_DestroyPublicKey(publickey);
00456     SECKEY_DestroyPrivateKey(ourPrivKey);
00457     publickey = NULL;
00458     ourPrivKey = NULL;
00459     
00460     if (!kek)
00461        goto loser;
00462 
00463     /* allocate space for the encrypted CEK (bulk key) */
00464     encKey->data = (unsigned char*)PORT_ArenaAlloc(poolp, SMIME_FORTEZZA_MAX_KEY_SIZE);
00465     encKey->len = SMIME_FORTEZZA_MAX_KEY_SIZE;
00466 
00467     if (encKey->data == NULL)
00468     {
00469        PK11_FreeSymKey(kek);
00470        goto loser;
00471     }
00472 
00473 
00474     /* Wrap the bulk key using CMSRC2WRAP or CMS3DESWRAP, depending on the */
00475     /* bulk encryption algorithm */
00476     switch (/* XXXX */PK11_AlgtagToMechanism(enccinfo->encalg))
00477     {
00478     case /* XXXX */CKM_SKIPJACK_CFB8:
00479        err = PK11_WrapSymKey(/* XXXX */CKM_CMS3DES_WRAP, NULL, kek, bulkkey, encKey);
00480        whichKEA = NSSCMSKEAUsesSkipjack;
00481        break;
00482     case /* XXXX */CKM_SKIPJACK_CFB8:
00483        err = PK11_WrapSymKey(/* XXXX */CKM_CMSRC2_WRAP, NULL, kek, bulkkey, encKey);
00484        whichKEA = NSSCMSKEAUsesSkipjack;
00485        break;
00486     default:
00487        /* XXXX what do we do here? Neither RC2 nor 3DES... */
00488         err = SECFailure;
00489         /* set error */
00490        break;
00491     }
00492 
00493     PK11_FreeSymKey(kek);   /* we do not need the KEK anymore */
00494     if (err != SECSuccess)
00495        goto loser;
00496 
00497     PORT_Assert(whichKEA != NSSCMSKEAInvalid);
00498 
00499     /* see RFC2630 12.3.1.1 "keyEncryptionAlgorithm must be ..." */
00500     /* params is the DER encoded key wrap algorithm (with parameters!) (XXX) */
00501     params = SEC_ASN1EncodeItem(arena, NULL, &keaParams, sec_pkcs7_get_kea_template(whichKEA));
00502     if (params == NULL)
00503        goto loser;
00504 
00505     /* now set keyEncAlg */
00506     rv = SECOID_SetAlgorithmID(poolp, keyEncAlg, SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN, params);
00507     if (rv != SECSuccess)
00508        goto loser;
00509 
00510     /* XXXXXXX this is not right yet */
00511 loser:
00512     if (arena) {
00513        PORT_FreeArena(arena, PR_FALSE);
00514     }
00515     if (publickey) {
00516         SECKEY_DestroyPublicKey(publickey);
00517     }
00518     if (ourPrivKey) {
00519         SECKEY_DestroyPrivateKey(ourPrivKey);
00520     }
00521 #endif
00522     return SECFailure;
00523 }
00524 
00525 PK11SymKey *
00526 NSS_CMSUtil_DecryptSymKey_ESDH(SECKEYPrivateKey *privkey, SECItem *encKey, SECAlgorithmID *keyEncAlg, SECOidTag bulkalgtag, void *pwfn_arg)
00527 {
00528 #if 0 /* not yet done */
00529     SECStatus err;
00530     CK_MECHANISM_TYPE bulkType;
00531     PK11SymKey *tek;
00532     SECKEYPublicKey *originatorPubKey;
00533     NSSCMSSMIMEKEAParameters keaParams;
00534 
00535    /* XXXX get originator's public key */
00536    originatorPubKey = PK11_MakeKEAPubKey(keaParams.originatorKEAKey.data,
00537                         keaParams.originatorKEAKey.len);
00538    if (originatorPubKey == NULL)
00539       goto loser;
00540     
00541    /* Generate the TEK (token exchange key) which we use to unwrap the bulk encryption key.
00542       The Derive function generates a shared secret and combines it with the originatorRA
00543       data to come up with an unique session key */
00544    tek = PK11_PubDerive(privkey, originatorPubKey, PR_FALSE,
00545                       &keaParams.originatorRA, NULL,
00546                       CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP,
00547                       CKA_WRAP, 0, pwfn_arg);
00548    SECKEY_DestroyPublicKey(originatorPubKey);    /* not needed anymore */
00549    if (tek == NULL)
00550        goto loser;
00551     
00552     /* Now that we have the TEK, unwrap the bulk key
00553        with which to decrypt the message. */
00554     /* Skipjack is being used as the bulk encryption algorithm.*/
00555     /* Unwrap the bulk key. */
00556     bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL,
00557                             encKey, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0);
00558 
00559     return bulkkey;
00560 
00561 loser:
00562 #endif
00563     return NULL;
00564 }
00565