Back to index

lightning-sunbird  0.9+nobinonly
pk11pbe.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 #include "plarena.h"
00038 
00039 #include "seccomon.h"
00040 #include "secitem.h"
00041 #include "secport.h"
00042 #include "hasht.h"
00043 #include "pkcs11t.h"
00044 #include "sechash.h"
00045 #include "secasn1.h"
00046 #include "secder.h"
00047 #include "secoid.h"
00048 #include "secerr.h"
00049 #include "secmod.h"
00050 #include "pk11func.h"
00051 #include "secpkcs5.h"
00052 #include "secmodi.h"
00053 #include "secmodti.h"
00054 #include "pkcs11.h"
00055 #include "pk11func.h"
00056 #include "secitem.h"
00057 #include "key.h"
00058 
00059 typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter;
00060 struct SEC_PKCS5PBEParameterStr {
00061     PRArenaPool *poolp;
00062     SECItem     salt;           /* octet string */
00063     SECItem     iteration;      /* integer */
00064 };
00065 
00066 
00067 /* template for PKCS 5 PBE Parameter.  This template has been expanded
00068  * based upon the additions in PKCS 12.  This should eventually be moved
00069  * if RSA updates PKCS 5.
00070  */
00071 const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] =
00072 {
00073     { SEC_ASN1_SEQUENCE, 
00074        0, NULL, sizeof(SEC_PKCS5PBEParameter) },
00075     { SEC_ASN1_OCTET_STRING, 
00076        offsetof(SEC_PKCS5PBEParameter, salt) },
00077     { SEC_ASN1_INTEGER,
00078        offsetof(SEC_PKCS5PBEParameter, iteration) },
00079     { 0 }
00080 };
00081 
00082 const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] =
00083 {   
00084     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
00085     { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
00086     { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
00087     { 0 }
00088 };
00089 
00090 /* maps crypto algorithm from PBE algorithm.
00091  */
00092 SECOidTag 
00093 SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
00094 {
00095 
00096     SECOidTag algorithm;
00097 
00098     if(algid == NULL)
00099        return SEC_OID_UNKNOWN;
00100 
00101     algorithm = SECOID_GetAlgorithmTag(algid);
00102     switch(algorithm)
00103     {
00104        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
00105        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
00106        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
00107            return SEC_OID_DES_EDE3_CBC;
00108        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
00109        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
00110        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
00111            return SEC_OID_DES_CBC;
00112        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
00113        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
00114        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
00115        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
00116            return SEC_OID_RC2_CBC;
00117        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
00118        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
00119        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
00120        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
00121            return SEC_OID_RC4;
00122        default:
00123            break;
00124     }
00125 
00126     return SEC_OID_UNKNOWN;
00127 }
00128 
00129 /* check to see if an oid is a pbe algorithm
00130  */ 
00131 PRBool 
00132 SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
00133 {
00134     return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN);
00135 }
00136 
00137 /* maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
00138  */
00139 SECOidTag 
00140 SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
00141 {
00142     switch(algTag)
00143     {
00144        case SEC_OID_DES_EDE3_CBC:
00145            switch(keyLen) {
00146               case 168:
00147               case 192:
00148                   return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
00149               case 128:
00150               case 92:
00151                   return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
00152               default:
00153                   break;
00154            }
00155            break;
00156        case SEC_OID_DES_CBC:
00157            return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
00158        case SEC_OID_RC2_CBC:
00159            switch(keyLen) {
00160               case 40:
00161                   return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
00162               case 128:
00163                   return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
00164               default:
00165                   break;
00166            }
00167            break;
00168        case SEC_OID_RC4:
00169            switch(keyLen) {
00170               case 40:
00171                   return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
00172               case 128:
00173                   return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
00174               default:
00175                   break;
00176            }
00177            break;
00178        default:
00179            break;
00180     }
00181 
00182     return SEC_OID_UNKNOWN;
00183 }
00184 
00185 
00186 /* get the key length needed for the PBE algorithm
00187  */
00188 
00189 int 
00190 SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
00191 {
00192 
00193     SECOidTag algorithm;
00194 
00195     if(algid == NULL)
00196        return SEC_OID_UNKNOWN;
00197 
00198     algorithm = SECOID_GetAlgorithmTag(algid);
00199 
00200     switch(algorithm)
00201     {
00202        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
00203        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
00204        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
00205            return 24;
00206        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
00207        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
00208        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
00209            return 8;
00210        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
00211        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
00212        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
00213        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
00214            return 5;
00215        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
00216        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
00217        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
00218        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
00219            return 16;
00220        default:
00221            break;
00222     }
00223     return -1;
00224 }
00225 
00226 
00227 /* the V2 algorithms only encode the salt, there is no iteration
00228  * count so we need a check for V2 algorithm parameters.
00229  */
00230 static PRBool
00231 sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
00232 {
00233     switch(algorithm) 
00234     {
00235        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
00236        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
00237        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
00238        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
00239        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
00240        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
00241            return PR_TRUE;
00242        default:
00243            break;
00244     }
00245 
00246     return PR_FALSE;
00247 }
00248 /* destroy a pbe parameter.  it assumes that the parameter was 
00249  * generated using the appropriate create function and therefor
00250  * contains an arena pool.
00251  */
00252 static void 
00253 sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
00254 {
00255     if(pbe_param != NULL)
00256        PORT_FreeArena(pbe_param->poolp, PR_TRUE);
00257 }
00258 
00259 /* creates a PBE parameter based on the PBE algorithm.  the only required
00260  * parameters are algorithm and interation.  the return is a PBE parameter
00261  * which conforms to PKCS 5 parameter unless an extended parameter is needed.
00262  * this is primarily if keyLen and a variable key length algorithm are
00263  * specified.
00264  *   salt -  if null, a salt will be generated from random bytes.
00265  *   iteration - number of iterations to perform hashing.
00266  *   keyLen - only used in variable key length algorithms
00267  *   iv - if null, the IV will be generated based on PKCS 5 when needed.
00268  *   params - optional, currently unsupported additional parameters.
00269  * once a parameter is allocated, it should be destroyed calling 
00270  * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
00271  */
00272 #define DEFAULT_SALT_LENGTH 16
00273 static SEC_PKCS5PBEParameter *
00274 sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, 
00275                      SECItem *salt, 
00276                      int iteration)
00277 {
00278     PRArenaPool *poolp = NULL;
00279     SEC_PKCS5PBEParameter *pbe_param = NULL;
00280     SECStatus rv= SECSuccess; 
00281     void *dummy = NULL;
00282 
00283     if(iteration < 0) {
00284        return NULL;
00285     }
00286 
00287     poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
00288     if(poolp == NULL)
00289        return NULL;
00290 
00291     pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
00292        sizeof(SEC_PKCS5PBEParameter));
00293     if(!pbe_param) {
00294        PORT_FreeArena(poolp, PR_TRUE);
00295        return NULL;
00296     }
00297 
00298     pbe_param->poolp = poolp;
00299 
00300     rv = SECFailure;
00301     if (salt && salt->data) {
00302        rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
00303     } else {
00304        /* sigh, the old interface generated salt on the fly, so we have to
00305         * preserve the semantics */
00306        pbe_param->salt.len = DEFAULT_SALT_LENGTH;
00307        pbe_param->salt.data = PORT_ArenaZAlloc(poolp,DEFAULT_SALT_LENGTH);
00308        if (pbe_param->salt.data) {
00309           rv = PK11_GenerateRandom(pbe_param->salt.data,DEFAULT_SALT_LENGTH);
00310        }
00311     }
00312 
00313     if(rv != SECSuccess) {
00314        PORT_FreeArena(poolp, PR_TRUE);
00315        return NULL;
00316     }
00317 
00318     /* encode the integer */
00319     dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, 
00320               iteration);
00321     rv = (dummy) ? SECSuccess : SECFailure;
00322 
00323     if(rv != SECSuccess) {
00324        PORT_FreeArena(poolp, PR_FALSE);
00325        return NULL;
00326     }
00327 
00328     return pbe_param;
00329 }
00330 
00331 /* creates a algorithm ID containing the PBE algorithm and appropriate
00332  * parameters.  the required parameter is the algorithm.  if salt is
00333  * not specified, it is generated randomly.  if IV is specified, it overrides
00334  * the PKCS 5 generation of the IV.  
00335  *
00336  * the returned SECAlgorithmID should be destroyed using 
00337  * SECOID_DestroyAlgorithmID
00338  */
00339 SECAlgorithmID *
00340 SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm, 
00341                         SECItem *salt, 
00342                         int iteration)
00343 {
00344     PRArenaPool *poolp = NULL;
00345     SECAlgorithmID *algid, *ret_algid;
00346     SECItem der_param;
00347     SECStatus rv = SECFailure;
00348     SEC_PKCS5PBEParameter *pbe_param;
00349 
00350     if(iteration <= 0) {
00351        return NULL;
00352     }
00353 
00354     der_param.data = NULL;
00355     der_param.len = 0;
00356 
00357     /* generate the parameter */
00358     pbe_param = sec_pkcs5_create_pbe_parameter(algorithm, salt, iteration);
00359     if(!pbe_param) {
00360        return NULL;
00361     }
00362 
00363     poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
00364     if(!poolp) {
00365        sec_pkcs5_destroy_pbe_param(pbe_param);
00366        return NULL;
00367     }
00368 
00369     /* generate the algorithm id */
00370     algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
00371     if(algid != NULL) {
00372        void *dummy;
00373        if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
00374            dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
00375                                    SEC_PKCS5PBEParameterTemplate);
00376        } else {
00377            dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
00378                                    SEC_V2PKCS12PBEParameterTemplate);
00379        }
00380        
00381        if(dummy) {
00382            rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
00383        }
00384     }
00385 
00386     ret_algid = NULL;
00387     if(algid != NULL) {
00388        ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
00389        if(ret_algid != NULL) {
00390            rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
00391            if(rv != SECSuccess) {
00392               SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
00393               ret_algid = NULL;
00394            }
00395        }
00396     }
00397        
00398     if(poolp != NULL) {
00399        PORT_FreeArena(poolp, PR_TRUE);
00400        algid = NULL;
00401     }
00402 
00403     sec_pkcs5_destroy_pbe_param(pbe_param);
00404 
00405     return ret_algid;
00406 }
00407 
00408 SECStatus
00409 pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech)
00410 {
00411     CK_PBE_PARAMS *pbe_params = NULL;
00412     SEC_PKCS5PBEParameter p5_param;
00413     SECItem *salt = NULL;
00414     SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
00415     PRArenaPool *arena = NULL;
00416     SECStatus rv = SECFailure;
00417     int iv_len;
00418     
00419 
00420     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
00421     if (arena == NULL) {
00422        goto loser;
00423     }
00424     iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
00425     if (iv_len < 0) {
00426        goto loser;
00427     }
00428 
00429     if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
00430         rv = SEC_ASN1DecodeItem(arena, &p5_param,
00431                       SEC_V2PKCS12PBEParameterTemplate, &algid->parameters);
00432     } else {
00433         rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate, 
00434                                           &algid->parameters);
00435     }
00436 
00437     if (rv != SECSuccess) {
00438        goto loser;
00439     }
00440         
00441     salt = &p5_param.salt;
00442 
00443     pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+
00444                                           salt->len+iv_len);
00445     if (pbe_params == NULL) {
00446        goto loser;
00447     }
00448 
00449     /* get salt */
00450     pbe_params->pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS);
00451     if (iv_len) {
00452        pbe_params->pInitVector = ((CK_CHAR_PTR) pbe_params)+
00453                                    sizeof(CK_PBE_PARAMS)+salt->len;
00454     }
00455     PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
00456     pbe_params->ulSaltLen = (CK_ULONG) salt->len;
00457 
00458     /* get iteration count */
00459     pbe_params->ulIteration = (CK_ULONG) DER_GetInteger(&p5_param.iteration);
00460 
00461     /* copy into the mechanism sec item */
00462     mech->data = (unsigned char *)pbe_params;
00463     mech->len = sizeof(*pbe_params);
00464     if (arena) {
00465        PORT_FreeArena(arena,PR_TRUE);
00466     }
00467     return SECSuccess;
00468 
00469 loser:
00470     if (pbe_params) {
00471        PORT_Free(pbe_params);
00472     }
00473     if (arena) {
00474        PORT_FreeArena(arena,PR_TRUE);
00475     }
00476     return SECFailure;
00477 }
00478 
00479 SECStatus
00480 PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena, 
00481                    SECAlgorithmID *algId)
00482 {
00483     CK_PBE_PARAMS *pbe_param;
00484     SECItem pbeSalt;
00485     SECAlgorithmID *pbeAlgID = NULL;
00486     SECStatus rv;
00487 
00488     if(!param || !algId) {
00489        return SECFailure;
00490     }
00491 
00492     pbe_param = (CK_PBE_PARAMS *)param->data;
00493     pbeSalt.data = (unsigned char *)pbe_param->pSalt;
00494     pbeSalt.len = pbe_param->ulSaltLen;
00495     pbeAlgID = SEC_PKCS5CreateAlgorithmID(algTag, &pbeSalt, 
00496                                      (int)pbe_param->ulIteration);
00497     if(!pbeAlgID) {
00498        return SECFailure;
00499     }
00500 
00501     rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
00502     SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
00503     return rv;
00504 }
00505 
00506 PBEBitGenContext *
00507 PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
00508        SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
00509        unsigned int iterations)
00510 {
00511     SECItem *context = NULL;
00512     SECItem mechItem;
00513     CK_PBE_PARAMS pbe_params;
00514     CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
00515     PK11SlotInfo *slot;
00516     PK11SymKey *symKey = NULL;
00517     unsigned char ivData[8];
00518     
00519 
00520     /* use the purpose to select the low level keygen algorithm */
00521     switch (bitGenPurpose) {
00522     case pbeBitGenIntegrityKey:
00523        switch (hashAlgorithm) {
00524        case SEC_OID_SHA1:
00525            mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC;
00526            break;
00527        case SEC_OID_MD2:
00528            mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN;
00529            break;
00530        case SEC_OID_MD5:
00531            mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN;
00532            break;
00533        default:
00534            break;
00535        }
00536        break;
00537     case pbeBitGenCipherIV:
00538        if (bitsNeeded > 64) {
00539            break;
00540        }
00541        if (hashAlgorithm != SEC_OID_SHA1) {
00542            break;
00543        }
00544        mechanism = CKM_PBE_SHA1_DES3_EDE_CBC;
00545        break;
00546     case pbeBitGenCipherKey:
00547        if (hashAlgorithm != SEC_OID_SHA1) {
00548            break;
00549        }
00550        switch (bitsNeeded) {
00551        case 40:
00552            mechanism = CKM_PBE_SHA1_RC4_40;
00553            break;
00554        case 128:
00555            mechanism = CKM_PBE_SHA1_RC4_128;
00556            break;
00557        default:
00558            break;
00559        }
00560     case pbeBitGenIDNull:
00561        break;
00562     }
00563 
00564     if (mechanism == CKM_INVALID_MECHANISM) {
00565        /* we should set an error, but this is a depricated function, and
00566         * we are keeping bug for bug compatibility;)... */
00567            return NULL;
00568     } 
00569 
00570     pbe_params.pInitVector = ivData;
00571     pbe_params.pPassword = pwitem->data;
00572     pbe_params.ulPasswordLen = pwitem->len;
00573     pbe_params.pSalt = salt->data;
00574     pbe_params.ulSaltLen = salt->len;
00575     pbe_params.ulIteration = iterations;
00576     mechItem.data = (unsigned char *) &pbe_params;
00577     mechItem.len = sizeof(pbe_params);
00578 
00579 
00580     slot = PK11_GetInternalSlot();
00581     symKey = PK11_RawPBEKeyGen(slot,mechanism,
00582                                    &mechItem, pwitem, PR_FALSE, NULL);
00583     PK11_FreeSlot(slot);
00584     if (symKey != NULL) {
00585        if (bitGenPurpose == pbeBitGenCipherIV) {
00586            /* NOTE: this assumes that bitsNeeded is a multiple of 8! */
00587            SECItem ivItem;
00588 
00589            ivItem.data = ivData;
00590            ivItem.len = bitsNeeded/8;
00591            context = SECITEM_DupItem(&ivItem);
00592        } else {
00593            SECItem *keyData;
00594            PK11_ExtractKeyValue(symKey);
00595            keyData = PK11_GetKeyData(symKey);
00596 
00597            /* assert bitsNeeded with length? */
00598            if (keyData) {
00599               context = SECITEM_DupItem(keyData);
00600            }
00601        }
00602        PK11_FreeSymKey(symKey);
00603     }
00604 
00605     return (PBEBitGenContext *)context;
00606 }
00607 
00608 SECItem *
00609 PBE_GenerateBits(PBEBitGenContext *context)
00610 {
00611     return (SECItem *)context;
00612 }
00613 
00614 void
00615 PBE_DestroyContext(PBEBitGenContext *context)
00616 {
00617     SECITEM_FreeItem((SECItem *)context,PR_TRUE);
00618 }
00619 
00620 SECItem *
00621 SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
00622 {
00623     SECItem mechItem;
00624     SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
00625     CK_PBE_PARAMS *pbe_params;
00626     CK_MECHANISM_TYPE mechanism;
00627     SECItem *iv = NULL;
00628     SECStatus rv;
00629     int iv_len;
00630     PK11SlotInfo *slot;
00631     PK11SymKey *symKey;
00632 
00633     rv = pbe_PK11AlgidToParam(algid,&mechItem);
00634     if (rv != SECSuccess) {
00635        return NULL;
00636     }
00637 
00638     mechanism = PK11_AlgtagToMechanism(algorithm);
00639     iv_len = PK11_GetIVLength(mechanism);
00640     pbe_params = (CK_PBE_PARAMS_PTR)mechItem.data;
00641 
00642     slot = PK11_GetInternalSlot();
00643     symKey = PK11_RawPBEKeyGen(slot,mechanism,
00644                                    &mechItem, pwitem, faulty3DES,NULL);
00645     PK11_FreeSlot(slot);
00646 
00647     if (symKey) {
00648        SECItem tmp;
00649 
00650        tmp.data = pbe_params->pInitVector;
00651        tmp.len = iv_len;
00652        iv = SECITEM_DupItem(&tmp);
00653         PK11_FreeSymKey(symKey);
00654     }
00655 
00656     if (mechItem.data) {
00657        PORT_ZFree(mechItem.data,mechItem.len);
00658     }
00659 
00660     return iv;
00661 }
00662 
00663 /*
00664  * Subs from nss 3.x that are depricated
00665  */
00666 PBEBitGenContext *
00667 __PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
00668        SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
00669        unsigned int iterations)
00670 {
00671     PORT_Assert("__PBE_CreateContext is Depricated" == NULL);
00672     return NULL;
00673 }
00674 
00675 SECItem *
00676 __PBE_GenerateBits(PBEBitGenContext *context)
00677 {
00678     PORT_Assert("__PBE_GenerateBits is Depricated" == NULL);
00679     return NULL;
00680 }
00681 
00682 void
00683 __PBE_DestroyContext(PBEBitGenContext *context)
00684 {
00685     PORT_Assert("__PBE_DestroyContext is Depricated" == NULL);
00686 }
00687 
00688 SECStatus
00689 RSA_FormatBlock(SECItem *result, unsigned modulusLen,
00690                 int blockType, SECItem *data)
00691 {
00692     PORT_Assert("RSA_FormatBlock is Depricated" == NULL);
00693     return SECFailure;
00694 }
00695 
00696 /****************************************************************************
00697  *
00698  * Now Do The PBE Functions Here...
00699  *
00700  ****************************************************************************/
00701 
00702 static void
00703 pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
00704 {
00705     if (pbe_params) {
00706        if (pbe_params->pPassword)
00707            PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen);
00708        if (pbe_params->pSalt)
00709            PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen);
00710        PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS));
00711     }
00712 }
00713 
00714 SECItem * 
00715 PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
00716 {
00717     CK_PBE_PARAMS *pbe_params = NULL;
00718     SECItem *paramRV = NULL;
00719 
00720     paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
00721     if (!paramRV ) {
00722        goto loser;
00723     }
00724     /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */
00725     PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS));
00726 
00727     pbe_params = (CK_PBE_PARAMS *)paramRV->data;
00728     pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
00729     if (!pbe_params->pPassword) {
00730         goto loser;
00731     }
00732     PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
00733     pbe_params->ulPasswordLen = pwd->len;
00734 
00735     pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
00736     if (!pbe_params->pSalt) {
00737        goto loser;
00738     }
00739     PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
00740     pbe_params->ulSaltLen = salt->len;
00741 
00742     pbe_params->ulIteration = (CK_ULONG)iterations;
00743     return paramRV;
00744 
00745 loser:
00746     if (pbe_params)
00747         pk11_destroy_ck_pbe_params(pbe_params);
00748     if (paramRV) 
00749        PORT_ZFree(paramRV, sizeof(SECItem));
00750     return NULL;
00751 }
00752 
00753 void
00754 PK11_DestroyPBEParams(SECItem *pItem)
00755 {
00756     if (pItem) {
00757        CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data);
00758        if (params)
00759            pk11_destroy_ck_pbe_params(params);
00760        PORT_ZFree(pItem, sizeof(SECItem));
00761     }
00762 }
00763 
00764 SECAlgorithmID *
00765 PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
00766 {
00767     SECAlgorithmID *algid = NULL;
00768     algid = SEC_PKCS5CreateAlgorithmID(algorithm, salt, iteration);
00769     return algid;
00770 }
00771 
00772 PK11SymKey *
00773 PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech,
00774                       SECItem *pwitem, PRBool faulty3DES, void *wincx)
00775 {
00776     /* pbe stuff */
00777     CK_PBE_PARAMS *pbe_params;
00778     PK11SymKey *symKey;
00779 
00780     if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
00781        type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
00782     }
00783     if(mech == NULL) {
00784        return NULL;
00785     }
00786 
00787     pbe_params = (CK_PBE_PARAMS *)mech->data;
00788     if (!pbe_params) {
00789        return NULL;
00790     }
00791     pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwitem->len);
00792     if(pbe_params->pPassword != NULL) {
00793        PORT_Memcpy(pbe_params->pPassword, pwitem->data, pwitem->len);
00794        pbe_params->ulPasswordLen = pwitem->len;
00795     } else {
00796        SECITEM_ZfreeItem(mech, PR_TRUE);
00797        return NULL;
00798     }
00799 
00800     symKey = PK11_TokenKeyGenWithFlags(slot, type, mech, 0, NULL,
00801            CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP, 0, wincx);
00802 
00803     PORT_ZFree(pbe_params->pPassword, pwitem->len);
00804     pbe_params->pPassword = NULL;
00805     pbe_params->ulPasswordLen = 0;
00806     return symKey;
00807 }
00808 
00809 PK11SymKey *
00810 PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
00811                                                  PRBool faulty3DES, void *wincx)
00812 {
00813     /* pbe stuff */
00814     CK_MECHANISM_TYPE type;
00815     SECItem *mech;
00816     PK11SymKey *symKey;
00817 
00818     mech = PK11_ParamFromAlgid(algid);
00819     type = PK11_AlgtagToMechanism(SECOID_FindOIDTag(&algid->algorithm));
00820     if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
00821        type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
00822     }
00823     if(mech == NULL) {
00824        return NULL;
00825     }
00826     symKey = PK11_RawPBEKeyGen(slot, type, mech, pwitem, faulty3DES, wincx);
00827 
00828     SECITEM_ZfreeItem(mech, PR_TRUE);
00829     return symKey;
00830 }
00831 
00832 SECItem *
00833 PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem)
00834 {
00835     /* pbe stuff */
00836     CK_MECHANISM_TYPE type;
00837     SECItem *mech;
00838     PK11SymKey *symKey;
00839     PK11SlotInfo *slot = PK11_GetInternalSlot();
00840     int iv_len = 0;
00841     CK_PBE_PARAMS_PTR pPBEparams;
00842     SECItem src;
00843     SECItem *iv;
00844 
00845 
00846     mech = PK11_ParamFromAlgid(algid);
00847     type = PK11_AlgtagToMechanism(SECOID_FindOIDTag(&algid->algorithm));
00848     if(mech == NULL) {
00849        return NULL;
00850     }
00851     symKey = PK11_RawPBEKeyGen(slot, type, mech, pwitem, PR_FALSE, NULL);
00852     PK11_FreeSlot(slot);
00853     if (symKey == NULL) {
00854        SECITEM_ZfreeItem(mech, PR_TRUE);
00855        return NULL;
00856     }
00857     PK11_FreeSymKey(symKey);
00858     pPBEparams = (CK_PBE_PARAMS_PTR)mech->data;
00859     iv_len = PK11_GetIVLength(type);
00860 
00861     src.data = (unsigned char *)pPBEparams->pInitVector;
00862     src.len = iv_len;
00863     iv = SECITEM_DupItem(&src);
00864 
00865     SECITEM_ZfreeItem(mech, PR_TRUE);
00866     return iv;
00867 }