security/nss/lib/pk11wrap/pk11pbe.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/pk11wrap/pk11pbe.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1432 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "plarena.h"
     1.9 +
    1.10 +#include "seccomon.h"
    1.11 +#include "secitem.h"
    1.12 +#include "secport.h"
    1.13 +#include "hasht.h"
    1.14 +#include "pkcs11t.h"
    1.15 +#include "sechash.h"
    1.16 +#include "secasn1.h"
    1.17 +#include "secder.h"
    1.18 +#include "secoid.h"
    1.19 +#include "secerr.h"
    1.20 +#include "secmod.h"
    1.21 +#include "pk11func.h"
    1.22 +#include "secpkcs5.h"
    1.23 +#include "secmodi.h"
    1.24 +#include "secmodti.h"
    1.25 +#include "pkcs11.h"
    1.26 +#include "pk11func.h"
    1.27 +#include "secitem.h"
    1.28 +#include "key.h"
    1.29 +
    1.30 +typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter;
    1.31 +struct SEC_PKCS5PBEParameterStr {
    1.32 +    PLArenaPool     *poolp;
    1.33 +    SECItem         salt;           /* octet string */
    1.34 +    SECItem         iteration;      /* integer */
    1.35 +    SECItem         keyLength;	/* PKCS5v2 only */
    1.36 +    SECAlgorithmID  *pPrfAlgId;	/* PKCS5v2 only */
    1.37 +    SECAlgorithmID  prfAlgId;	/* PKCS5v2 only */
    1.38 +};
    1.39 +
    1.40 +/* PKCS5 V2 has an algorithm ID for the encryption and for 
    1.41 + * the key generation. This is valid for SEC_OID_PKCS5_PBES2 
    1.42 + * and SEC_OID_PKCS5_PBMAC1
    1.43 + */
    1.44 +struct sec_pkcs5V2ParameterStr {
    1.45 +    PLArenaPool    *poolp;
    1.46 +    SECAlgorithmID pbeAlgId;   /* real pbe algorithms */
    1.47 +    SECAlgorithmID cipherAlgId; /* encryption/mac */
    1.48 +};
    1.49 +
    1.50 +typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter;
    1.51 +
    1.52 +
    1.53 +/* template for PKCS 5 PBE Parameter.  This template has been expanded
    1.54 + * based upon the additions in PKCS 12.  This should eventually be moved
    1.55 + * if RSA updates PKCS 5.
    1.56 + */
    1.57 +const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] =
    1.58 +{
    1.59 +    { SEC_ASN1_SEQUENCE, 
    1.60 +	0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    1.61 +    { SEC_ASN1_OCTET_STRING, 
    1.62 +	offsetof(SEC_PKCS5PBEParameter, salt) },
    1.63 +    { SEC_ASN1_INTEGER,
    1.64 +	offsetof(SEC_PKCS5PBEParameter, iteration) },
    1.65 +    { 0 }
    1.66 +};
    1.67 +
    1.68 +const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] =
    1.69 +{   
    1.70 +    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    1.71 +    { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
    1.72 +    { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
    1.73 +    { 0 }
    1.74 +};
    1.75 +
    1.76 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
    1.77 +
    1.78 +/* SECOID_PKCS5_PBKDF2 */
    1.79 +const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] =
    1.80 +{   
    1.81 +    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    1.82 +    /* This is really a choice, but since we only understand this
    1.83 +     * choice, just inline it */
    1.84 +    { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
    1.85 +    { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
    1.86 +    { SEC_ASN1_INTEGER|SEC_ASN1_OPTIONAL, 
    1.87 +		      offsetof(SEC_PKCS5PBEParameter, keyLength) },
    1.88 +    { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL, 
    1.89 +	offsetof(SEC_PKCS5PBEParameter, pPrfAlgId),
    1.90 +	SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
    1.91 +    { 0 }
    1.92 +};
    1.93 +
    1.94 +/* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
    1.95 +const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] =
    1.96 +{   
    1.97 +    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    1.98 +    { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId),
    1.99 +	SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
   1.100 +    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
   1.101 +	offsetof(sec_pkcs5V2Parameter, cipherAlgId),
   1.102 +	SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
   1.103 +    { 0 }
   1.104 +};
   1.105 +
   1.106 +
   1.107 +/*
   1.108 + * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1
   1.109 + * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2.
   1.110 + */
   1.111 +SECOidTag
   1.112 +sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm)
   1.113 +{
   1.114 +    switch(algorithm)
   1.115 +    {
   1.116 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
   1.117 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
   1.118 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
   1.119 +	    return SEC_OID_DES_EDE3_CBC;
   1.120 +	case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
   1.121 +	case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
   1.122 +	case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
   1.123 +	    return SEC_OID_DES_CBC;
   1.124 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   1.125 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   1.126 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   1.127 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   1.128 +	    return SEC_OID_RC2_CBC;
   1.129 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
   1.130 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
   1.131 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
   1.132 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
   1.133 +	    return SEC_OID_RC4;
   1.134 +	case SEC_OID_PKCS5_PBKDF2:
   1.135 +	case SEC_OID_PKCS5_PBES2:
   1.136 +	case SEC_OID_PKCS5_PBMAC1:
   1.137 +	    return SEC_OID_PKCS5_PBKDF2;
   1.138 +	default:
   1.139 +	    break;
   1.140 +    }
   1.141 +
   1.142 +    return SEC_OID_UNKNOWN;
   1.143 +}
   1.144 +
   1.145 +/*
   1.146 + * get a new PKCS5 V2 Parameter from the algorithm id.
   1.147 + *  if arena is passed in, use it, otherwise create a new arena.
   1.148 + */
   1.149 +sec_pkcs5V2Parameter *
   1.150 +sec_pkcs5_v2_get_v2_param(PLArenaPool *arena, SECAlgorithmID *algid)
   1.151 +{
   1.152 +    PLArenaPool *localArena = NULL;
   1.153 +    sec_pkcs5V2Parameter *pbeV2_param;
   1.154 +    SECStatus rv;
   1.155 +
   1.156 +    if (arena == NULL) {
   1.157 +	localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   1.158 +	if (arena == NULL) {
   1.159 +	    return NULL;
   1.160 +	}
   1.161 +    }
   1.162 +    pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter);
   1.163 +    if (pbeV2_param == NULL) {
   1.164 +	goto loser;
   1.165 +    }
   1.166 +	
   1.167 +    rv = SEC_ASN1DecodeItem(arena, pbeV2_param,
   1.168 +		SEC_PKCS5V2ParameterTemplate, &algid->parameters);
   1.169 +    if (rv == SECFailure) {
   1.170 +	goto loser;
   1.171 +    }
   1.172 +
   1.173 +    pbeV2_param->poolp = arena;
   1.174 +    return pbeV2_param;
   1.175 +loser:
   1.176 +    if (localArena) {
   1.177 +	PORT_FreeArena(arena, PR_FALSE);
   1.178 +    }
   1.179 +    return NULL;
   1.180 +}
   1.181 +
   1.182 +void
   1.183 +sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param)
   1.184 +{
   1.185 +   if (param && param->poolp) {
   1.186 +	PORT_FreeArena(param->poolp, PR_TRUE);
   1.187 +   }
   1.188 +}
   1.189 +	
   1.190 +
   1.191 +/* maps crypto algorithm from PBE algorithm.
   1.192 + */
   1.193 +SECOidTag 
   1.194 +SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
   1.195 +{
   1.196 +
   1.197 +    SECOidTag pbeAlg;
   1.198 +    SECOidTag cipherAlg;
   1.199 +
   1.200 +    if(algid == NULL)
   1.201 +	return SEC_OID_UNKNOWN;
   1.202 +
   1.203 +    pbeAlg = SECOID_GetAlgorithmTag(algid);
   1.204 +    cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg);
   1.205 +    if ((cipherAlg == SEC_OID_PKCS5_PBKDF2)  &&
   1.206 +	 (pbeAlg != SEC_OID_PKCS5_PBKDF2)) {
   1.207 +	sec_pkcs5V2Parameter *pbeV2_param;
   1.208 +	cipherAlg = SEC_OID_UNKNOWN;
   1.209 +
   1.210 +	pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
   1.211 +	if (pbeV2_param != NULL) {
   1.212 +	    cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId);
   1.213 +	    sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
   1.214 +	}
   1.215 +    }
   1.216 +
   1.217 +    return cipherAlg;
   1.218 +}
   1.219 +
   1.220 +/* check to see if an oid is a pbe algorithm
   1.221 + */ 
   1.222 +PRBool 
   1.223 +SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
   1.224 +{
   1.225 +    return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN);
   1.226 +}
   1.227 +
   1.228 +PRBool 
   1.229 +SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag)
   1.230 +{
   1.231 +    return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN);
   1.232 +}
   1.233 +
   1.234 +/*
   1.235 + * find the most appropriate PKCS5v2 overall oid tag from a regular
   1.236 + * cipher/hash algorithm tag.
   1.237 + */
   1.238 +static SECOidTag
   1.239 +sec_pkcs5v2_get_pbe(SECOidTag algTag)
   1.240 +{
   1.241 +    /* if it's a valid hash oid... */
   1.242 +    if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) {
   1.243 +	/* use the MAC tag */
   1.244 +	return SEC_OID_PKCS5_PBMAC1;
   1.245 +    }
   1.246 +    if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) {
   1.247 +	/* eliminate Hash algorithms */
   1.248 +	return SEC_OID_UNKNOWN;
   1.249 +    }
   1.250 +    if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) {
   1.251 +	/* it's not a hash, if it has a PKCS #11 mechanism associated
   1.252 +	 * with it, assume it's a cipher. (NOTE this will generate
   1.253 +	 * some false positives). */
   1.254 +	return SEC_OID_PKCS5_PBES2;
   1.255 +    }
   1.256 +    return SEC_OID_UNKNOWN;
   1.257 +}
   1.258 +
   1.259 +/* 
   1.260 + * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
   1.261 + *  input keyLen in bits.
   1.262 + */
   1.263 +SECOidTag 
   1.264 +SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
   1.265 +{
   1.266 +    switch(algTag)
   1.267 +    {
   1.268 +	case SEC_OID_DES_EDE3_CBC:
   1.269 +	    switch(keyLen) {
   1.270 +		case 168:
   1.271 +		case 192:
   1.272 +		case 0:
   1.273 +		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
   1.274 +		case 128:
   1.275 +		case 92:
   1.276 +		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
   1.277 +		default:
   1.278 +		    break;
   1.279 +	    }
   1.280 +	    break;
   1.281 +	case SEC_OID_DES_CBC:
   1.282 +	    return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
   1.283 +	case SEC_OID_RC2_CBC:
   1.284 +	    switch(keyLen) {
   1.285 +		case 40:
   1.286 +		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
   1.287 +		case 128:
   1.288 +		case 0:
   1.289 +		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
   1.290 +		default:
   1.291 +		    break;
   1.292 +	    }
   1.293 +	    break;
   1.294 +	case SEC_OID_RC4:
   1.295 +	    switch(keyLen) {
   1.296 +		case 40:
   1.297 +		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
   1.298 +		case 128:
   1.299 +		case 0:
   1.300 +		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
   1.301 +		default:
   1.302 +		    break;
   1.303 +	    }
   1.304 +	    break;
   1.305 +	default:
   1.306 +	    return sec_pkcs5v2_get_pbe(algTag);
   1.307 +    }
   1.308 +
   1.309 +    return SEC_OID_UNKNOWN;
   1.310 +}
   1.311 +
   1.312 +/*
   1.313 + * get the key length in bytes from a PKCS5 PBE
   1.314 + */
   1.315 +int
   1.316 +sec_pkcs5v2_key_length(SECAlgorithmID *algid)
   1.317 +{
   1.318 +    SECOidTag algorithm;
   1.319 +    PLArenaPool *arena = NULL;
   1.320 +    SEC_PKCS5PBEParameter p5_param;
   1.321 +    SECStatus rv;
   1.322 +    int length = -1;
   1.323 +
   1.324 +    algorithm = SECOID_GetAlgorithmTag(algid);
   1.325 +    /* sanity check, they should all be PBKDF2 here */
   1.326 +    if (algorithm != SEC_OID_PKCS5_PBKDF2) {
   1.327 +	return -1;
   1.328 +    }
   1.329 +
   1.330 +    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   1.331 +    if (arena == NULL) {
   1.332 +	goto loser;
   1.333 +    }
   1.334 +    PORT_Memset(&p5_param, 0, sizeof(p5_param));
   1.335 +    rv = SEC_ASN1DecodeItem(arena,&p5_param,
   1.336 +			 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
   1.337 +    if (rv != SECSuccess) {
   1.338 +	goto loser;
   1.339 +    }
   1.340 +
   1.341 +    if (p5_param.keyLength.data != NULL) {
   1.342 +        length = DER_GetInteger(&p5_param.keyLength);
   1.343 +    }
   1.344 +
   1.345 +loser:
   1.346 +    if (arena) {
   1.347 +	PORT_FreeArena(arena, PR_FALSE);
   1.348 +    }
   1.349 +    return length;
   1.350 +}
   1.351 +
   1.352 +/*
   1.353 + *  get the key length in bytes needed for the PBE algorithm
   1.354 + */
   1.355 +int 
   1.356 +SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
   1.357 +{
   1.358 +
   1.359 +    SECOidTag algorithm;
   1.360 +
   1.361 +    if(algid == NULL)
   1.362 +	return SEC_OID_UNKNOWN;
   1.363 +
   1.364 +    algorithm = SECOID_GetAlgorithmTag(algid);
   1.365 +
   1.366 +    switch(algorithm)
   1.367 +    {
   1.368 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
   1.369 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
   1.370 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
   1.371 +	    return 24;
   1.372 +	case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
   1.373 +	case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
   1.374 +	case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
   1.375 +	    return 8;
   1.376 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   1.377 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
   1.378 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
   1.379 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   1.380 +	    return 5;
   1.381 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   1.382 +	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
   1.383 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   1.384 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
   1.385 +	    return 16;
   1.386 +	case SEC_OID_PKCS5_PBKDF2:
   1.387 +	    return sec_pkcs5v2_key_length(algid);
   1.388 +	case SEC_OID_PKCS5_PBES2:
   1.389 +	case SEC_OID_PKCS5_PBMAC1:
   1.390 +	    {
   1.391 +		sec_pkcs5V2Parameter *pbeV2_param;
   1.392 +		int length = -1;
   1.393 +		pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
   1.394 +		if (pbeV2_param != NULL) {
   1.395 +	    	    length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId);
   1.396 +		    sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
   1.397 +		}
   1.398 +		return length;
   1.399 +	    }
   1.400 +	
   1.401 +	default:
   1.402 +	    break;
   1.403 +    }
   1.404 +    return -1;
   1.405 +}
   1.406 +
   1.407 +
   1.408 +/* the PKCS12 V2 algorithms only encode the salt, there is no iteration
   1.409 + * count so we need a check for V2 algorithm parameters.
   1.410 + */
   1.411 +static PRBool
   1.412 +sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
   1.413 +{
   1.414 +    switch(algorithm) 
   1.415 +    {
   1.416 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
   1.417 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
   1.418 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
   1.419 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
   1.420 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   1.421 +	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   1.422 +	    return PR_TRUE;
   1.423 +	default:
   1.424 +	    break;
   1.425 +    }
   1.426 +
   1.427 +    return PR_FALSE;
   1.428 +}
   1.429 +
   1.430 +static PRBool
   1.431 +sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm)
   1.432 +{
   1.433 +    switch(algorithm) 
   1.434 +    {
   1.435 +	case SEC_OID_PKCS5_PBES2:
   1.436 +	case SEC_OID_PKCS5_PBMAC1:
   1.437 +	case SEC_OID_PKCS5_PBKDF2:
   1.438 +	    return PR_TRUE;
   1.439 +	default:
   1.440 +	    break;
   1.441 +    }
   1.442 +
   1.443 +    return PR_FALSE;
   1.444 +}
   1.445 +
   1.446 +/* destroy a pbe parameter.  it assumes that the parameter was 
   1.447 + * generated using the appropriate create function and therefor
   1.448 + * contains an arena pool.
   1.449 + */
   1.450 +static void 
   1.451 +sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
   1.452 +{
   1.453 +    if(pbe_param != NULL)
   1.454 +	PORT_FreeArena(pbe_param->poolp, PR_TRUE);
   1.455 +}
   1.456 +
   1.457 +/* creates a PBE parameter based on the PBE algorithm.  the only required
   1.458 + * parameters are algorithm and interation.  the return is a PBE parameter
   1.459 + * which conforms to PKCS 5 parameter unless an extended parameter is needed.
   1.460 + * this is primarily if keyLength and a variable key length algorithm are
   1.461 + * specified.
   1.462 + *   salt -  if null, a salt will be generated from random bytes.
   1.463 + *   iteration - number of iterations to perform hashing.
   1.464 + *   keyLength - only used in variable key length algorithms. if specified,
   1.465 + *            should be in bytes.
   1.466 + * once a parameter is allocated, it should be destroyed calling 
   1.467 + * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
   1.468 + */
   1.469 +#define DEFAULT_SALT_LENGTH 16
   1.470 +static SEC_PKCS5PBEParameter *
   1.471 +sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, 
   1.472 +			SECItem *salt, 
   1.473 +			int iteration,
   1.474 +			int keyLength,
   1.475 +			SECOidTag prfAlg)
   1.476 +{
   1.477 +    PLArenaPool *poolp = NULL;
   1.478 +    SEC_PKCS5PBEParameter *pbe_param = NULL;
   1.479 +    SECStatus rv= SECSuccess; 
   1.480 +    void *dummy = NULL;
   1.481 +
   1.482 +    if(iteration < 0) {
   1.483 +	return NULL;
   1.484 +    }
   1.485 +
   1.486 +    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   1.487 +    if(poolp == NULL)
   1.488 +	return NULL;
   1.489 +
   1.490 +    pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
   1.491 +	sizeof(SEC_PKCS5PBEParameter));
   1.492 +    if(!pbe_param) {
   1.493 +	PORT_FreeArena(poolp, PR_TRUE);
   1.494 +	return NULL;
   1.495 +    }
   1.496 +
   1.497 +    pbe_param->poolp = poolp;
   1.498 +
   1.499 +    rv = SECFailure;
   1.500 +    if (salt && salt->data) {
   1.501 +    	rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
   1.502 +    } else {
   1.503 +	/* sigh, the old interface generated salt on the fly, so we have to
   1.504 +	 * preserve the semantics */
   1.505 +	pbe_param->salt.len = DEFAULT_SALT_LENGTH;
   1.506 +	pbe_param->salt.data = PORT_ArenaZAlloc(poolp,DEFAULT_SALT_LENGTH);
   1.507 +	if (pbe_param->salt.data) {
   1.508 +	   rv = PK11_GenerateRandom(pbe_param->salt.data,DEFAULT_SALT_LENGTH);
   1.509 +	}
   1.510 +    }
   1.511 +
   1.512 +    if(rv != SECSuccess) {
   1.513 +	PORT_FreeArena(poolp, PR_TRUE);
   1.514 +	return NULL;
   1.515 +    }
   1.516 +
   1.517 +    /* encode the integer */
   1.518 +    dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, 
   1.519 +		iteration);
   1.520 +    rv = (dummy) ? SECSuccess : SECFailure;
   1.521 +
   1.522 +    if(rv != SECSuccess) {
   1.523 +	PORT_FreeArena(poolp, PR_FALSE);
   1.524 +	return NULL;
   1.525 +    }
   1.526 +
   1.527 +    /*
   1.528 +     * for PKCS5 v2 Add the keylength and the prf
   1.529 +     */
   1.530 +    if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   1.531 +	dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength, 
   1.532 +		keyLength);
   1.533 +	rv = (dummy) ? SECSuccess : SECFailure;
   1.534 +	if (rv != SECSuccess) {
   1.535 +	    PORT_FreeArena(poolp, PR_FALSE);
   1.536 +	    return NULL;
   1.537 +	}
   1.538 +	rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL);
   1.539 +	if (rv != SECSuccess) {
   1.540 +	    PORT_FreeArena(poolp, PR_FALSE);
   1.541 +	    return NULL;
   1.542 +	}
   1.543 +	pbe_param->pPrfAlgId = &pbe_param->prfAlgId;
   1.544 +    }
   1.545 +
   1.546 +    return pbe_param;
   1.547 +}
   1.548 +
   1.549 +/* creates a algorithm ID containing the PBE algorithm and appropriate
   1.550 + * parameters.  the required parameter is the algorithm.  if salt is
   1.551 + * not specified, it is generated randomly.  
   1.552 + *
   1.553 + * the returned SECAlgorithmID should be destroyed using 
   1.554 + * SECOID_DestroyAlgorithmID
   1.555 + */
   1.556 +SECAlgorithmID *
   1.557 +sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, 
   1.558 +			   SECOidTag cipherAlgorithm,
   1.559 +			   SECOidTag prfAlg,
   1.560 +			   SECOidTag *pPbeAlgorithm,
   1.561 +			   int keyLength,
   1.562 +			   SECItem *salt, 
   1.563 +			   int iteration)
   1.564 +{
   1.565 +    PLArenaPool *poolp = NULL;
   1.566 +    SECAlgorithmID *algid, *ret_algid = NULL;
   1.567 +    SECOidTag pbeAlgorithm = algorithm;
   1.568 +    SECItem der_param;
   1.569 +    void *dummy;
   1.570 +    SECStatus rv = SECFailure;
   1.571 +    SEC_PKCS5PBEParameter *pbe_param = NULL;
   1.572 +    sec_pkcs5V2Parameter pbeV2_param;
   1.573 +
   1.574 +    if(iteration <= 0) {
   1.575 +	return NULL;
   1.576 +    }
   1.577 +
   1.578 +    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   1.579 +    if(!poolp) {
   1.580 +	goto loser;
   1.581 +    }
   1.582 +
   1.583 +    if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) ||
   1.584 +    	 	sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
   1.585 +	/* use PKCS 5 v2 */
   1.586 +	SECItem *cipherParams;
   1.587 +
   1.588 +	/*
   1.589 +	 * if we ask for pkcs5 Algorithms directly, then the
   1.590 +	 * application needs to supply the cipher algorithm,
   1.591 +	 * otherwise we are implicitly using pkcs5 v2 and the
   1.592 +	 * passed in algorithm is the encryption algorithm.
   1.593 +	 */
   1.594 +	if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
   1.595 +	    if (cipherAlgorithm == SEC_OID_UNKNOWN) {
   1.596 +		goto loser;
   1.597 +	    }
   1.598 +	} else {
   1.599 +	    cipherAlgorithm = algorithm;
   1.600 +	    /* force algorithm to be chosen below */
   1.601 +	    algorithm = SEC_OID_PKCS5_PBKDF2;
   1.602 +	}
   1.603 +	
   1.604 +	pbeAlgorithm = SEC_OID_PKCS5_PBKDF2;
   1.605 +	/*
   1.606 +	 * 'algorithm' is the overall algorithm oid tag used to wrap the 
   1.607 +	 * entire algoithm ID block. For PKCS5v1 and PKCS12, this 
   1.608 +	 * algorithm OID has encoded in it both the PBE KDF function 
   1.609 +	 * and the encryption algorithm. For PKCS 5v2, PBE KDF and
   1.610 +	 * encryption/macing oids are encoded as parameters in
   1.611 +	 * the algorithm ID block. 
   1.612 +	 *
   1.613 +	 * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11
   1.614 +	 * mechanism, where as in PKCS 5v2, this alogithm tag does not map
   1.615 +	 * directly to a PKCS #11 mechanim, instead the 2 oids in the 
   1.616 +	 * algorithm ID block map the the actual PKCS #11 mechanism.
   1.617 +	 * gorithm is). We use choose this algorithm oid based on the 
   1.618 +	 * cipherAlgorithm to determine what this should be (MAC1 or PBES2).
   1.619 +	 */
   1.620 +	if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   1.621 +	     /* choose mac or pbes */
   1.622 +	     algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
   1.623 +	}
   1.624 +
   1.625 +	/* set the PKCS5v2 specific parameters */
   1.626 +	if (keyLength == 0) {
   1.627 +	    SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
   1.628 +    	    if (hashAlg != SEC_OID_UNKNOWN) {
   1.629 +	        keyLength = HASH_ResultLenByOidTag(hashAlg);
   1.630 +	    } else {
   1.631 +		CK_MECHANISM_TYPE cryptoMech;
   1.632 +		cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm);
   1.633 +		if (cryptoMech == CKM_INVALID_MECHANISM) {
   1.634 +		    goto loser;
   1.635 +		}
   1.636 +	        keyLength = PK11_GetMaxKeyLength(cryptoMech);
   1.637 +	    }
   1.638 +	    if (keyLength == 0) {
   1.639 +		goto loser;
   1.640 +	    }
   1.641 +	}
   1.642 +	/* currently only SEC_OID_HMAC_SHA1 is defined */
   1.643 +	if (prfAlg == SEC_OID_UNKNOWN) {
   1.644 +	    prfAlg = SEC_OID_HMAC_SHA1;
   1.645 +	}
   1.646 +
   1.647 +	/* build the PKCS5v2 cipher algorithm id */
   1.648 +	cipherParams = pk11_GenerateNewParamWithKeyLen(	
   1.649 +			PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
   1.650 +	if (!cipherParams) {
   1.651 +	    goto loser;
   1.652 +	}
   1.653 +
   1.654 +	PORT_Memset(&pbeV2_param, 0, sizeof (pbeV2_param));
   1.655 +
   1.656 +	rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams, 
   1.657 +				poolp, &pbeV2_param.cipherAlgId);
   1.658 +	SECITEM_FreeItem(cipherParams, PR_TRUE);
   1.659 +	if (rv != SECSuccess) {
   1.660 +	    goto loser;
   1.661 +	}
   1.662 +    }
   1.663 +	
   1.664 +
   1.665 +    /* generate the parameter */
   1.666 +    pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration,
   1.667 +			keyLength, prfAlg);
   1.668 +    if(!pbe_param) {
   1.669 +	goto loser;
   1.670 +    }
   1.671 +
   1.672 +    /* generate the algorithm id */
   1.673 +    algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
   1.674 +    if(algid == NULL) {
   1.675 +	goto loser;
   1.676 +    }
   1.677 +
   1.678 +    der_param.data = NULL;
   1.679 +    der_param.len = 0;
   1.680 +    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
   1.681 +	/* first encode the PBE algorithm ID */
   1.682 +	dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
   1.683 +					SEC_PKCS5V2PBEParameterTemplate);
   1.684 +	if (dummy == NULL) {
   1.685 +	    goto loser;
   1.686 +	}
   1.687 +	rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId, 
   1.688 +				   pbeAlgorithm, &der_param);
   1.689 +	if (rv != SECSuccess) {
   1.690 +	    goto loser;
   1.691 +	}
   1.692 +
   1.693 +	/* now encode the Full PKCS 5 parameter */
   1.694 +	der_param.data = NULL;
   1.695 +	der_param.len = 0;
   1.696 +	dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param,
   1.697 +					SEC_PKCS5V2ParameterTemplate);
   1.698 +    } else if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
   1.699 +	dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
   1.700 +					SEC_PKCS5PBEParameterTemplate);
   1.701 +    } else {
   1.702 +	dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
   1.703 +	    				SEC_V2PKCS12PBEParameterTemplate);
   1.704 +    }
   1.705 +    if (dummy == NULL) {
   1.706 +	goto loser;
   1.707 +    }
   1.708 +
   1.709 +    rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
   1.710 +    if (rv != SECSuccess) {
   1.711 +	goto loser;
   1.712 +    }
   1.713 +
   1.714 +    ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
   1.715 +    if (ret_algid == NULL) {
   1.716 +	goto loser;
   1.717 +    }
   1.718 +
   1.719 +    rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
   1.720 +    if (rv != SECSuccess) {
   1.721 +	SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
   1.722 +	ret_algid = NULL;
   1.723 +    } else if (pPbeAlgorithm) {
   1.724 +	*pPbeAlgorithm = pbeAlgorithm;
   1.725 +    }
   1.726 +
   1.727 +loser:
   1.728 +    if (poolp != NULL) {
   1.729 +	PORT_FreeArena(poolp, PR_TRUE);
   1.730 +	algid = NULL;
   1.731 +    }
   1.732 +
   1.733 +    if (pbe_param) {
   1.734 +	sec_pkcs5_destroy_pbe_param(pbe_param);
   1.735 +    }
   1.736 +
   1.737 +    return ret_algid;
   1.738 +}
   1.739 +
   1.740 +SECStatus
   1.741 +pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech)
   1.742 +{
   1.743 +    SEC_PKCS5PBEParameter p5_param;
   1.744 +    SECItem *salt = NULL;
   1.745 +    SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
   1.746 +    PLArenaPool *arena = NULL;
   1.747 +    SECStatus rv = SECFailure;
   1.748 +    unsigned char *paramData = NULL;
   1.749 +    unsigned char *pSalt = NULL;
   1.750 +    CK_ULONG iterations;
   1.751 +    int paramLen = 0;
   1.752 +    int iv_len;
   1.753 +    
   1.754 +
   1.755 +    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   1.756 +    if (arena == NULL) {
   1.757 +	goto loser;
   1.758 +    }
   1.759 +
   1.760 +
   1.761 +    /*
   1.762 +     * decode the algid based on the pbe type
   1.763 +     */
   1.764 +    PORT_Memset(&p5_param, 0, sizeof(p5_param));
   1.765 +    if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
   1.766 +        iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
   1.767 +        rv = SEC_ASN1DecodeItem(arena, &p5_param,
   1.768 +			 SEC_V2PKCS12PBEParameterTemplate, &algid->parameters);
   1.769 +    } else if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   1.770 +	iv_len = 0;
   1.771 +        rv = SEC_ASN1DecodeItem(arena,&p5_param,
   1.772 +			 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
   1.773 +    } else {
   1.774 +        iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
   1.775 +        rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate, 
   1.776 +						&algid->parameters);
   1.777 +    }
   1.778 +
   1.779 +    if (iv_len < 0) {
   1.780 +	goto loser;
   1.781 +    }
   1.782 +
   1.783 +    if (rv != SECSuccess) {
   1.784 +	goto loser;
   1.785 +    }
   1.786 +        
   1.787 +    /* get salt */
   1.788 +    salt = &p5_param.salt;
   1.789 +    iterations = (CK_ULONG) DER_GetInteger(&p5_param.iteration);
   1.790 +
   1.791 +    /* allocate and fill in the PKCS #11 parameters
   1.792 +     * based on the algorithm. */
   1.793 +    if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   1.794 +	SECOidTag prfAlgTag;
   1.795 +    	CK_PKCS5_PBKD2_PARAMS *pbeV2_params = 
   1.796 +		(CK_PKCS5_PBKD2_PARAMS *)PORT_ZAlloc(
   1.797 +			sizeof(CK_PKCS5_PBKD2_PARAMS)+ salt->len);
   1.798 +
   1.799 +	if (pbeV2_params == NULL) {
   1.800 +	    goto loser;
   1.801 +	}
   1.802 +	paramData = (unsigned char *)pbeV2_params;
   1.803 +	paramLen = sizeof(CK_PKCS5_PBKD2_PARAMS);
   1.804 +
   1.805 +	/* set the prf */
   1.806 +	prfAlgTag = SEC_OID_HMAC_SHA1;
   1.807 + 	if (p5_param.pPrfAlgId &&
   1.808 + 	    p5_param.pPrfAlgId->algorithm.data != 0) {
   1.809 + 	    prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId);
   1.810 +	}
   1.811 +	if (prfAlgTag == SEC_OID_HMAC_SHA1) {
   1.812 +	    pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
   1.813 +	} else {
   1.814 +	    /* only SHA1_HMAC is currently supported by PKCS #11 */
   1.815 +	    PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1.816 +	    goto loser;
   1.817 +	}
   1.818 +	
   1.819 +	/* probably should fetch these from the prfAlgid */
   1.820 +	pbeV2_params->pPrfData = NULL;
   1.821 +	pbeV2_params->ulPrfDataLen = 0;
   1.822 +	pbeV2_params->saltSource = CKZ_SALT_SPECIFIED;
   1.823 +	pSalt = ((CK_CHAR_PTR) pbeV2_params)+sizeof(CK_PKCS5_PBKD2_PARAMS);
   1.824 +        PORT_Memcpy(pSalt, salt->data, salt->len);
   1.825 +	pbeV2_params->pSaltSourceData = pSalt;
   1.826 +	pbeV2_params->ulSaltSourceDataLen = salt->len;
   1.827 +	pbeV2_params->iterations = iterations;
   1.828 +    } else {
   1.829 +	CK_PBE_PARAMS *pbe_params = NULL;
   1.830 +    	pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+
   1.831 +						salt->len+iv_len);
   1.832 +	if (pbe_params == NULL) {
   1.833 +	    goto loser;
   1.834 +	}
   1.835 +	paramData = (unsigned char *)pbe_params;
   1.836 +	paramLen = sizeof(CK_PBE_PARAMS);
   1.837 +
   1.838 +	pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS);
   1.839 +    	pbe_params->pSalt = pSalt;
   1.840 +        PORT_Memcpy(pSalt, salt->data, salt->len);
   1.841 +	pbe_params->ulSaltLen = salt->len;
   1.842 +	if (iv_len) {
   1.843 +	    pbe_params->pInitVector = 
   1.844 +		((CK_CHAR_PTR) pbe_params)+ sizeof(CK_PBE_PARAMS)+salt->len;
   1.845 +	}
   1.846 +	pbe_params->ulIteration = iterations;
   1.847 +    }
   1.848 +
   1.849 +    /* copy into the mechanism sec item */
   1.850 +    mech->data = paramData;
   1.851 +    mech->len = paramLen;
   1.852 +    if (arena) {
   1.853 +	PORT_FreeArena(arena,PR_TRUE);
   1.854 +    }
   1.855 +    return SECSuccess;
   1.856 +
   1.857 +loser:
   1.858 +    if (paramData) {
   1.859 +	PORT_Free(paramData);
   1.860 +    }
   1.861 +    if (arena) {
   1.862 +	PORT_FreeArena(arena,PR_TRUE);
   1.863 +    }
   1.864 +    return SECFailure;
   1.865 +}
   1.866 +
   1.867 +/*
   1.868 + * public, deprecated, not valid for pkcs5 v2 
   1.869 + * 
   1.870 + * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create
   1.871 + * PBE algorithmID's directly.
   1.872 + */
   1.873 +SECStatus
   1.874 +PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena,
   1.875 +		     SECAlgorithmID *algId)
   1.876 +{
   1.877 +    CK_PBE_PARAMS *pbe_param;
   1.878 +    SECItem pbeSalt;
   1.879 +    SECAlgorithmID *pbeAlgID = NULL;
   1.880 +    SECStatus rv;
   1.881 +
   1.882 +    if(!param || !algId) {
   1.883 +	return SECFailure;
   1.884 +    }
   1.885 +
   1.886 +    pbe_param = (CK_PBE_PARAMS *)param->data;
   1.887 +    pbeSalt.data = (unsigned char *)pbe_param->pSalt;
   1.888 +    pbeSalt.len = pbe_param->ulSaltLen;
   1.889 +    pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, 
   1.890 +	SEC_OID_UNKNOWN, NULL, 0, &pbeSalt, (int)pbe_param->ulIteration);
   1.891 +    if(!pbeAlgID) {
   1.892 +	return SECFailure;
   1.893 +    }
   1.894 +
   1.895 +    rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
   1.896 +    SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
   1.897 +    return rv;
   1.898 +}
   1.899 +
   1.900 +/*
   1.901 + * public, Deprecated, This function is only for binary compatibility with 
   1.902 + * older applications. Does not support PKCS5v2.
   1.903 + *
   1.904 + * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
   1.905 + * iv values rather than generating PBE bits directly.
   1.906 + */
   1.907 +PBEBitGenContext *
   1.908 +PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
   1.909 +	SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
   1.910 +	unsigned int iterations)
   1.911 +{
   1.912 +    SECItem *context = NULL;
   1.913 +    SECItem mechItem;
   1.914 +    CK_PBE_PARAMS pbe_params;
   1.915 +    CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
   1.916 +    PK11SlotInfo *slot;
   1.917 +    PK11SymKey *symKey = NULL;
   1.918 +    unsigned char ivData[8];
   1.919 +    
   1.920 +
   1.921 +    /* use the purpose to select the low level keygen algorithm */
   1.922 +    switch (bitGenPurpose) {
   1.923 +    case pbeBitGenIntegrityKey:
   1.924 +	switch (hashAlgorithm) {
   1.925 +	case SEC_OID_SHA1:
   1.926 +	    mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC;
   1.927 +	    break;
   1.928 +	case SEC_OID_MD2:
   1.929 +	    mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN;
   1.930 +	    break;
   1.931 +	case SEC_OID_MD5:
   1.932 +	    mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN;
   1.933 +	    break;
   1.934 +	default:
   1.935 +	    break;
   1.936 +	}
   1.937 +	break;
   1.938 +    case pbeBitGenCipherIV:
   1.939 +	if (bitsNeeded > 64) {
   1.940 +	    break;
   1.941 +	}
   1.942 +	if (hashAlgorithm != SEC_OID_SHA1) {
   1.943 +	    break;
   1.944 +	}
   1.945 +	mechanism = CKM_PBE_SHA1_DES3_EDE_CBC;
   1.946 +	break;
   1.947 +    case pbeBitGenCipherKey:
   1.948 +	if (hashAlgorithm != SEC_OID_SHA1) {
   1.949 +	    break;
   1.950 +	}
   1.951 +	switch (bitsNeeded) {
   1.952 +	case 40:
   1.953 +	    mechanism = CKM_PBE_SHA1_RC4_40;
   1.954 +	    break;
   1.955 +	case 128:
   1.956 +	    mechanism = CKM_PBE_SHA1_RC4_128;
   1.957 +	    break;
   1.958 +	default:
   1.959 +	    break;
   1.960 +	}
   1.961 +    case pbeBitGenIDNull:
   1.962 +	break;
   1.963 +    }
   1.964 +
   1.965 +    if (mechanism == CKM_INVALID_MECHANISM) {
   1.966 +	/* we should set an error, but this is a deprecated function, and
   1.967 +	 * we are keeping bug for bug compatibility;)... */
   1.968 +	    return NULL;
   1.969 +    } 
   1.970 +
   1.971 +    pbe_params.pInitVector = ivData;
   1.972 +    pbe_params.pPassword = pwitem->data;
   1.973 +    pbe_params.ulPasswordLen = pwitem->len;
   1.974 +    pbe_params.pSalt = salt->data;
   1.975 +    pbe_params.ulSaltLen = salt->len;
   1.976 +    pbe_params.ulIteration = iterations;
   1.977 +    mechItem.data = (unsigned char *) &pbe_params;
   1.978 +    mechItem.len = sizeof(pbe_params);
   1.979 +
   1.980 +
   1.981 +    slot = PK11_GetInternalSlot();
   1.982 +    symKey = PK11_RawPBEKeyGen(slot,mechanism,
   1.983 +					&mechItem, pwitem, PR_FALSE, NULL);
   1.984 +    PK11_FreeSlot(slot);
   1.985 +    if (symKey != NULL) {
   1.986 +	if (bitGenPurpose == pbeBitGenCipherIV) {
   1.987 +	    /* NOTE: this assumes that bitsNeeded is a multiple of 8! */
   1.988 +	    SECItem ivItem;
   1.989 +
   1.990 +	    ivItem.data = ivData;
   1.991 +	    ivItem.len = bitsNeeded/8;
   1.992 +	    context = SECITEM_DupItem(&ivItem);
   1.993 +	} else {
   1.994 +	    SECItem *keyData;
   1.995 +	    PK11_ExtractKeyValue(symKey);
   1.996 +	    keyData = PK11_GetKeyData(symKey);
   1.997 +
   1.998 +	    /* assert bitsNeeded with length? */
   1.999 +	    if (keyData) {
  1.1000 +	    	context = SECITEM_DupItem(keyData);
  1.1001 +	    }
  1.1002 +	}
  1.1003 +	PK11_FreeSymKey(symKey);
  1.1004 +    }
  1.1005 +
  1.1006 +    return (PBEBitGenContext *)context;
  1.1007 +}
  1.1008 +
  1.1009 +/*
  1.1010 + * public, Deprecated, This function is only for binary compatibility with 
  1.1011 + * older applications. Does not support PKCS5v2.
  1.1012 + * 
  1.1013 + * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for
  1.1014 + * iv values rather than generating PBE bits directly.
  1.1015 + */
  1.1016 +SECItem *
  1.1017 +PBE_GenerateBits(PBEBitGenContext *context)
  1.1018 +{
  1.1019 +    return (SECItem *)context;
  1.1020 +}
  1.1021 +
  1.1022 +/*
  1.1023 + * public, Deprecated, This function is only for binary compatibility with 
  1.1024 + * older applications. Does not support PKCS5v2.
  1.1025 + * 
  1.1026 + * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
  1.1027 + * iv values rather than generating PBE bits directly.
  1.1028 + */
  1.1029 +void
  1.1030 +PBE_DestroyContext(PBEBitGenContext *context)
  1.1031 +{
  1.1032 +    SECITEM_FreeItem((SECItem *)context,PR_TRUE);
  1.1033 +}
  1.1034 +
  1.1035 +/*
  1.1036 + * public, deprecated. Replaced with PK11_GetPBEIV().
  1.1037 + */
  1.1038 +SECItem *
  1.1039 +SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
  1.1040 +{
  1.1041 +    /* pbe stuff */
  1.1042 +    CK_MECHANISM_TYPE type;
  1.1043 +    SECItem *param = NULL;
  1.1044 +    SECItem *iv = NULL;
  1.1045 +    SECItem src;
  1.1046 +    int iv_len = 0;
  1.1047 +    PK11SymKey *symKey;
  1.1048 +    PK11SlotInfo *slot;
  1.1049 +    CK_PBE_PARAMS_PTR pPBEparams;
  1.1050 +    SECOidTag	pbeAlg;
  1.1051 +
  1.1052 +    pbeAlg = SECOID_GetAlgorithmTag(algid);
  1.1053 +    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
  1.1054 +	unsigned char *ivData;
  1.1055 +	sec_pkcs5V2Parameter *pbeV2_param = NULL;
  1.1056 +
  1.1057 +	/* can only return the IV if the crypto Algorithm exists */
  1.1058 +	if (pbeAlg == SEC_OID_PKCS5_PBKDF2) {
  1.1059 +	    PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1.1060 +	    goto loser;
  1.1061 +	}
  1.1062 +	pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
  1.1063 +	if (pbeV2_param == NULL) {
  1.1064 +	    goto loser;
  1.1065 +	}
  1.1066 +	/* extract the IV from the cipher algid portion of our pkcs 5 v2
  1.1067 +	 * algorithm id */
  1.1068 +    	type = PK11_AlgtagToMechanism(
  1.1069 +    		SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
  1.1070 +	param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId);
  1.1071 +	sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
  1.1072 +	if (!param) {
  1.1073 +	    goto loser;
  1.1074 +	}
  1.1075 +	/* NOTE: NULL is a permissible return here */
  1.1076 +	ivData = PK11_IVFromParam(type, param, &iv_len);
  1.1077 +	src.data = ivData;
  1.1078 +	src.len = iv_len;
  1.1079 +	goto done;
  1.1080 +    }
  1.1081 +
  1.1082 +    type = PK11_AlgtagToMechanism(pbeAlg);
  1.1083 +    param = PK11_ParamFromAlgid(algid);
  1.1084 +    if (param == NULL) {
  1.1085 +	goto done;
  1.1086 +    }
  1.1087 +    slot = PK11_GetInternalSlot();
  1.1088 +    symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL);
  1.1089 +    PK11_FreeSlot(slot);
  1.1090 +    if (symKey == NULL) {
  1.1091 +	goto loser;
  1.1092 +    }
  1.1093 +    PK11_FreeSymKey(symKey);
  1.1094 +    pPBEparams = (CK_PBE_PARAMS_PTR)param->data;
  1.1095 +    iv_len = PK11_GetIVLength(type);
  1.1096 +
  1.1097 +    src.data = (unsigned char *)pPBEparams->pInitVector;
  1.1098 +    src.len = iv_len;
  1.1099 +
  1.1100 +done:
  1.1101 +    iv = SECITEM_DupItem(&src);
  1.1102 +
  1.1103 +loser:
  1.1104 +    if (param) {
  1.1105 +	SECITEM_ZfreeItem(param, PR_TRUE);
  1.1106 +    }
  1.1107 +    return iv;
  1.1108 +}
  1.1109 +
  1.1110 +/*
  1.1111 + * Subs from nss 3.x that are deprecated
  1.1112 + */
  1.1113 +PBEBitGenContext *
  1.1114 +__PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
  1.1115 +	SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
  1.1116 +	unsigned int iterations)
  1.1117 +{
  1.1118 +    PORT_Assert("__PBE_CreateContext is Deprecated" == NULL);
  1.1119 +    return NULL;
  1.1120 +}
  1.1121 +
  1.1122 +SECItem *
  1.1123 +__PBE_GenerateBits(PBEBitGenContext *context)
  1.1124 +{
  1.1125 +    PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL);
  1.1126 +    return NULL;
  1.1127 +}
  1.1128 +
  1.1129 +void
  1.1130 +__PBE_DestroyContext(PBEBitGenContext *context)
  1.1131 +{
  1.1132 +    PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL);
  1.1133 +}
  1.1134 +
  1.1135 +SECStatus
  1.1136 +RSA_FormatBlock(SECItem *result, unsigned modulusLen,
  1.1137 +                int blockType, SECItem *data)
  1.1138 +{
  1.1139 +    PORT_Assert("RSA_FormatBlock is Deprecated" == NULL);
  1.1140 +    return SECFailure;
  1.1141 +}
  1.1142 +
  1.1143 +/****************************************************************************
  1.1144 + *
  1.1145 + * Now Do The PBE Functions Here...
  1.1146 + *
  1.1147 + ****************************************************************************/
  1.1148 +
  1.1149 +static void
  1.1150 +pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
  1.1151 +{
  1.1152 +    if (pbe_params) {
  1.1153 +	if (pbe_params->pPassword)
  1.1154 +	    PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen);
  1.1155 +	if (pbe_params->pSalt)
  1.1156 +	    PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen);
  1.1157 +	PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS));
  1.1158 +    }
  1.1159 +}
  1.1160 +
  1.1161 +/*
  1.1162 + * public, deprecated.  use PK11_CreatePBEAlgorithmID or 
  1.1163 + * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters, 
  1.1164 + * use PK11_ParamFromAlgid from the algorithm id you created using 
  1.1165 + * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID.
  1.1166 + */
  1.1167 +SECItem * 
  1.1168 +PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
  1.1169 +{
  1.1170 +    CK_PBE_PARAMS *pbe_params = NULL;
  1.1171 +    SECItem *paramRV = NULL;
  1.1172 +
  1.1173 +    paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
  1.1174 +    if (!paramRV ) {
  1.1175 +	goto loser;
  1.1176 +    }
  1.1177 +    /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */
  1.1178 +    PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS));
  1.1179 +
  1.1180 +    pbe_params = (CK_PBE_PARAMS *)paramRV->data;
  1.1181 +    pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
  1.1182 +    if (!pbe_params->pPassword) {
  1.1183 +        goto loser;
  1.1184 +    }
  1.1185 +    PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
  1.1186 +    pbe_params->ulPasswordLen = pwd->len;
  1.1187 +
  1.1188 +    pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
  1.1189 +    if (!pbe_params->pSalt) {
  1.1190 +	goto loser;
  1.1191 +    }
  1.1192 +    PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
  1.1193 +    pbe_params->ulSaltLen = salt->len;
  1.1194 +
  1.1195 +    pbe_params->ulIteration = (CK_ULONG)iterations;
  1.1196 +    return paramRV;
  1.1197 +
  1.1198 +loser:
  1.1199 +    if (pbe_params)
  1.1200 +        pk11_destroy_ck_pbe_params(pbe_params);
  1.1201 +    if (paramRV) 
  1.1202 +    	PORT_ZFree(paramRV, sizeof(SECItem));
  1.1203 +    return NULL;
  1.1204 +}
  1.1205 +
  1.1206 +/*
  1.1207 + * public, deprecated.
  1.1208 + */
  1.1209 +void
  1.1210 +PK11_DestroyPBEParams(SECItem *pItem)
  1.1211 +{
  1.1212 +    if (pItem) {
  1.1213 +	CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data);
  1.1214 +	if (params)
  1.1215 +	    pk11_destroy_ck_pbe_params(params);
  1.1216 +	PORT_ZFree(pItem, sizeof(SECItem));
  1.1217 +    }
  1.1218 +}
  1.1219 +
  1.1220 +/*
  1.1221 + * public, Partially supports PKCS5 V2 (some parameters are not controllable
  1.1222 + * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need
  1.1223 + * finer control these.
  1.1224 + */
  1.1225 +SECAlgorithmID *
  1.1226 +PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
  1.1227 +{
  1.1228 +    SECAlgorithmID *algid = NULL;
  1.1229 +    algid = sec_pkcs5CreateAlgorithmID(algorithm,
  1.1230 +		 SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL, 0, salt, iteration);
  1.1231 +    return algid;
  1.1232 +}
  1.1233 +
  1.1234 +/*
  1.1235 + * public, fully support pkcs5v2.
  1.1236 + */
  1.1237 +SECAlgorithmID *
  1.1238 +PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag,
  1.1239 +			    SECOidTag prfAlgTag, int keyLength, int iteration, 
  1.1240 +			    SECItem *salt)
  1.1241 +{
  1.1242 +    SECAlgorithmID *algid = NULL;
  1.1243 +    algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag,
  1.1244 +					NULL, keyLength, salt, iteration);
  1.1245 +    return algid;
  1.1246 +}
  1.1247 +
  1.1248 +/*
  1.1249 + * private.
  1.1250 + */
  1.1251 +PK11SymKey *
  1.1252 +pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 
  1.1253 +			SECItem *params, CK_KEY_TYPE keyType, int keyLen,
  1.1254 +			SECItem *pwitem, void *wincx)
  1.1255 +{
  1.1256 +    CK_ULONG pwLen;
  1.1257 +    /* do some sanity checks */
  1.1258 +    if ((params == NULL) || (params->data == NULL)) {
  1.1259 +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.1260 +	return NULL;
  1.1261 +    }
  1.1262 +
  1.1263 +    if (type == CKM_INVALID_MECHANISM) {
  1.1264 +	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1.1265 +	return NULL;
  1.1266 +    }
  1.1267 +
  1.1268 +    /* set the password pointer in the parameters... */
  1.1269 +    if (type == CKM_PKCS5_PBKD2) {
  1.1270 +    	CK_PKCS5_PBKD2_PARAMS *pbev2_params;
  1.1271 +	if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) {
  1.1272 +	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.1273 +	    return NULL;
  1.1274 +	}
  1.1275 +	pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data;
  1.1276 +	pbev2_params->pPassword = pwitem->data;
  1.1277 +	pwLen = pwitem->len;
  1.1278 +	pbev2_params->ulPasswordLen = &pwLen;
  1.1279 +    } else {
  1.1280 +    	CK_PBE_PARAMS *pbe_params;
  1.1281 +	if (params->len < sizeof(CK_PBE_PARAMS)) {
  1.1282 +	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.1283 +	    return NULL;
  1.1284 +	}
  1.1285 +	pbe_params = (CK_PBE_PARAMS *)params->data;
  1.1286 +	pbe_params->pPassword = pwitem->data;
  1.1287 +	pbe_params->ulPasswordLen = pwitem->len;
  1.1288 +    }
  1.1289 +
  1.1290 +    /* generate the key (and sometimes the IV as a side effect...) */
  1.1291 +    return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType, 
  1.1292 +	   keyLen, NULL, CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP, 
  1.1293 +	   0, wincx);
  1.1294 +}
  1.1295 +
  1.1296 +/*
  1.1297 + * public, deprecated. use PK11_PBEKeyGen instead.
  1.1298 + */
  1.1299 +PK11SymKey *
  1.1300 +PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech,
  1.1301 +			 SECItem *pwitem, PRBool faulty3DES, void *wincx)
  1.1302 +{
  1.1303 +    if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
  1.1304 +	type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
  1.1305 +    }
  1.1306 +    return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx);
  1.1307 +}
  1.1308 +
  1.1309 +/*
  1.1310 + * pubic, supports pkcs5 v2.
  1.1311 + *
  1.1312 + * Create symkey from a PBE key. The algid can be created with
  1.1313 + *  PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by
  1.1314 + *  extraction of der data.
  1.1315 + */
  1.1316 +PK11SymKey *
  1.1317 +PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
  1.1318 +	       					PRBool faulty3DES, void *wincx)
  1.1319 +{
  1.1320 +    CK_MECHANISM_TYPE type;
  1.1321 +    SECItem *param = NULL;
  1.1322 +    PK11SymKey *symKey = NULL;
  1.1323 +    SECOidTag	pbeAlg;
  1.1324 +    CK_KEY_TYPE keyType = -1;
  1.1325 +    int keyLen = 0;
  1.1326 +
  1.1327 +    pbeAlg = SECOID_GetAlgorithmTag(algid);
  1.1328 +    /* if we're using PKCS5v2, extract the additional information we need
  1.1329 +     * (key length, key type, and pbeAlg). */
  1.1330 +    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
  1.1331 +	CK_MECHANISM_TYPE cipherMech;
  1.1332 +	sec_pkcs5V2Parameter *pbeV2_param;
  1.1333 +
  1.1334 +	pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
  1.1335 +	if (pbeV2_param == NULL) {
  1.1336 +	    return NULL;
  1.1337 +	}
  1.1338 +	cipherMech = PK11_AlgtagToMechanism(
  1.1339 +		SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
  1.1340 +	pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
  1.1341 +	param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId);
  1.1342 +	sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
  1.1343 +	keyLen = SEC_PKCS5GetKeyLength(algid);
  1.1344 +	if (keyLen == -1) {
  1.1345 +	    keyLen = 0;
  1.1346 +	}
  1.1347 +	keyType = PK11_GetKeyType(cipherMech, keyLen);
  1.1348 +    } else {
  1.1349 +	param = PK11_ParamFromAlgid(algid);
  1.1350 +    }
  1.1351 +
  1.1352 +    if(param == NULL) {
  1.1353 +	goto loser;
  1.1354 +    }
  1.1355 +
  1.1356 +    type = PK11_AlgtagToMechanism(pbeAlg);	
  1.1357 +    if (type == CKM_INVALID_MECHANISM) {
  1.1358 +	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1.1359 +	goto loser;
  1.1360 +    }
  1.1361 +    if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
  1.1362 +	type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
  1.1363 +    }
  1.1364 +    symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen, 
  1.1365 +					pwitem, wincx);
  1.1366 +
  1.1367 +loser:
  1.1368 +    if (param) {
  1.1369 +	SECITEM_ZfreeItem(param, PR_TRUE);
  1.1370 +    }
  1.1371 +    return symKey;
  1.1372 +}
  1.1373 +
  1.1374 +/*
  1.1375 + * public, supports pkcs5v2
  1.1376 + */
  1.1377 +SECItem *
  1.1378 +PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem)
  1.1379 +{
  1.1380 +    return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE);
  1.1381 +}
  1.1382 +
  1.1383 +CK_MECHANISM_TYPE
  1.1384 +pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, 
  1.1385 +			   SECItem *pbe_pwd, PRBool faulty3DES)
  1.1386 +{
  1.1387 +    int keyLen = 0;
  1.1388 +    SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid);
  1.1389 +    CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag);
  1.1390 +    CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM;
  1.1391 +    SECItem *iv = NULL;
  1.1392 +
  1.1393 +    if (mech == CKM_INVALID_MECHANISM) {
  1.1394 +	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1.1395 +	goto loser;
  1.1396 +    }
  1.1397 +    if (PK11_GetIVLength(mech)) {
  1.1398 +	iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES);
  1.1399 +	if (iv == NULL) {
  1.1400 +	    goto loser;
  1.1401 +	}
  1.1402 +    }
  1.1403 +
  1.1404 +    keyLen = SEC_PKCS5GetKeyLength(algid);
  1.1405 +
  1.1406 +    *param = pk11_ParamFromIVWithLen(mech, iv, keyLen);
  1.1407 +    if (*param == NULL) {
  1.1408 +	goto loser;
  1.1409 +    }
  1.1410 +    returnedMechanism = mech;
  1.1411 +
  1.1412 +loser:
  1.1413 +    if (iv) {
  1.1414 +	SECITEM_FreeItem(iv,PR_TRUE);
  1.1415 +    }
  1.1416 +    return returnedMechanism;
  1.1417 +}
  1.1418 +
  1.1419 +/*
  1.1420 + * Public, supports pkcs5 v2
  1.1421 + *
  1.1422 + * Get the crypto mechanism directly from the pbe algorithmid.
  1.1423 + *
  1.1424 + * It's important to go directly from the algorithm id so that we can
  1.1425 + * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases.
  1.1426 + *
  1.1427 + * This function returns both the mechanism and the parameter for the mechanism.
  1.1428 + * The caller is responsible for freeing the parameter.
  1.1429 + */
  1.1430 +CK_MECHANISM_TYPE
  1.1431 +PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, 
  1.1432 +			   SECItem *pbe_pwd)
  1.1433 +{
  1.1434 +    return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE);
  1.1435 +}

mercurial