security/nss/lib/pk11wrap/pk11pbe.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "plarena.h"
     7 #include "seccomon.h"
     8 #include "secitem.h"
     9 #include "secport.h"
    10 #include "hasht.h"
    11 #include "pkcs11t.h"
    12 #include "sechash.h"
    13 #include "secasn1.h"
    14 #include "secder.h"
    15 #include "secoid.h"
    16 #include "secerr.h"
    17 #include "secmod.h"
    18 #include "pk11func.h"
    19 #include "secpkcs5.h"
    20 #include "secmodi.h"
    21 #include "secmodti.h"
    22 #include "pkcs11.h"
    23 #include "pk11func.h"
    24 #include "secitem.h"
    25 #include "key.h"
    27 typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter;
    28 struct SEC_PKCS5PBEParameterStr {
    29     PLArenaPool     *poolp;
    30     SECItem         salt;           /* octet string */
    31     SECItem         iteration;      /* integer */
    32     SECItem         keyLength;	/* PKCS5v2 only */
    33     SECAlgorithmID  *pPrfAlgId;	/* PKCS5v2 only */
    34     SECAlgorithmID  prfAlgId;	/* PKCS5v2 only */
    35 };
    37 /* PKCS5 V2 has an algorithm ID for the encryption and for 
    38  * the key generation. This is valid for SEC_OID_PKCS5_PBES2 
    39  * and SEC_OID_PKCS5_PBMAC1
    40  */
    41 struct sec_pkcs5V2ParameterStr {
    42     PLArenaPool    *poolp;
    43     SECAlgorithmID pbeAlgId;   /* real pbe algorithms */
    44     SECAlgorithmID cipherAlgId; /* encryption/mac */
    45 };
    47 typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter;
    50 /* template for PKCS 5 PBE Parameter.  This template has been expanded
    51  * based upon the additions in PKCS 12.  This should eventually be moved
    52  * if RSA updates PKCS 5.
    53  */
    54 const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] =
    55 {
    56     { SEC_ASN1_SEQUENCE, 
    57 	0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    58     { SEC_ASN1_OCTET_STRING, 
    59 	offsetof(SEC_PKCS5PBEParameter, salt) },
    60     { SEC_ASN1_INTEGER,
    61 	offsetof(SEC_PKCS5PBEParameter, iteration) },
    62     { 0 }
    63 };
    65 const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] =
    66 {   
    67     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    68     { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
    69     { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
    70     { 0 }
    71 };
    73 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
    75 /* SECOID_PKCS5_PBKDF2 */
    76 const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] =
    77 {   
    78     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    79     /* This is really a choice, but since we only understand this
    80      * choice, just inline it */
    81     { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
    82     { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
    83     { SEC_ASN1_INTEGER|SEC_ASN1_OPTIONAL, 
    84 		      offsetof(SEC_PKCS5PBEParameter, keyLength) },
    85     { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL, 
    86 	offsetof(SEC_PKCS5PBEParameter, pPrfAlgId),
    87 	SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
    88     { 0 }
    89 };
    91 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
    92 const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] =
    93 {   
    94     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
    95     { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId),
    96 	SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
    97     { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
    98 	offsetof(sec_pkcs5V2Parameter, cipherAlgId),
    99 	SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
   100     { 0 }
   101 };
   104 /*
   105  * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1
   106  * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2.
   107  */
   108 SECOidTag
   109 sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm)
   110 {
   111     switch(algorithm)
   112     {
   113 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
   114 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
   115 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
   116 	    return SEC_OID_DES_EDE3_CBC;
   117 	case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
   118 	case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
   119 	case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
   120 	    return SEC_OID_DES_CBC;
   121 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   122 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   123 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   124 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   125 	    return SEC_OID_RC2_CBC;
   126 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
   127 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
   128 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
   129 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
   130 	    return SEC_OID_RC4;
   131 	case SEC_OID_PKCS5_PBKDF2:
   132 	case SEC_OID_PKCS5_PBES2:
   133 	case SEC_OID_PKCS5_PBMAC1:
   134 	    return SEC_OID_PKCS5_PBKDF2;
   135 	default:
   136 	    break;
   137     }
   139     return SEC_OID_UNKNOWN;
   140 }
   142 /*
   143  * get a new PKCS5 V2 Parameter from the algorithm id.
   144  *  if arena is passed in, use it, otherwise create a new arena.
   145  */
   146 sec_pkcs5V2Parameter *
   147 sec_pkcs5_v2_get_v2_param(PLArenaPool *arena, SECAlgorithmID *algid)
   148 {
   149     PLArenaPool *localArena = NULL;
   150     sec_pkcs5V2Parameter *pbeV2_param;
   151     SECStatus rv;
   153     if (arena == NULL) {
   154 	localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   155 	if (arena == NULL) {
   156 	    return NULL;
   157 	}
   158     }
   159     pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter);
   160     if (pbeV2_param == NULL) {
   161 	goto loser;
   162     }
   164     rv = SEC_ASN1DecodeItem(arena, pbeV2_param,
   165 		SEC_PKCS5V2ParameterTemplate, &algid->parameters);
   166     if (rv == SECFailure) {
   167 	goto loser;
   168     }
   170     pbeV2_param->poolp = arena;
   171     return pbeV2_param;
   172 loser:
   173     if (localArena) {
   174 	PORT_FreeArena(arena, PR_FALSE);
   175     }
   176     return NULL;
   177 }
   179 void
   180 sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param)
   181 {
   182    if (param && param->poolp) {
   183 	PORT_FreeArena(param->poolp, PR_TRUE);
   184    }
   185 }
   188 /* maps crypto algorithm from PBE algorithm.
   189  */
   190 SECOidTag 
   191 SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
   192 {
   194     SECOidTag pbeAlg;
   195     SECOidTag cipherAlg;
   197     if(algid == NULL)
   198 	return SEC_OID_UNKNOWN;
   200     pbeAlg = SECOID_GetAlgorithmTag(algid);
   201     cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg);
   202     if ((cipherAlg == SEC_OID_PKCS5_PBKDF2)  &&
   203 	 (pbeAlg != SEC_OID_PKCS5_PBKDF2)) {
   204 	sec_pkcs5V2Parameter *pbeV2_param;
   205 	cipherAlg = SEC_OID_UNKNOWN;
   207 	pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
   208 	if (pbeV2_param != NULL) {
   209 	    cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId);
   210 	    sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
   211 	}
   212     }
   214     return cipherAlg;
   215 }
   217 /* check to see if an oid is a pbe algorithm
   218  */ 
   219 PRBool 
   220 SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
   221 {
   222     return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN);
   223 }
   225 PRBool 
   226 SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag)
   227 {
   228     return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN);
   229 }
   231 /*
   232  * find the most appropriate PKCS5v2 overall oid tag from a regular
   233  * cipher/hash algorithm tag.
   234  */
   235 static SECOidTag
   236 sec_pkcs5v2_get_pbe(SECOidTag algTag)
   237 {
   238     /* if it's a valid hash oid... */
   239     if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) {
   240 	/* use the MAC tag */
   241 	return SEC_OID_PKCS5_PBMAC1;
   242     }
   243     if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) {
   244 	/* eliminate Hash algorithms */
   245 	return SEC_OID_UNKNOWN;
   246     }
   247     if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) {
   248 	/* it's not a hash, if it has a PKCS #11 mechanism associated
   249 	 * with it, assume it's a cipher. (NOTE this will generate
   250 	 * some false positives). */
   251 	return SEC_OID_PKCS5_PBES2;
   252     }
   253     return SEC_OID_UNKNOWN;
   254 }
   256 /* 
   257  * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
   258  *  input keyLen in bits.
   259  */
   260 SECOidTag 
   261 SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
   262 {
   263     switch(algTag)
   264     {
   265 	case SEC_OID_DES_EDE3_CBC:
   266 	    switch(keyLen) {
   267 		case 168:
   268 		case 192:
   269 		case 0:
   270 		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
   271 		case 128:
   272 		case 92:
   273 		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
   274 		default:
   275 		    break;
   276 	    }
   277 	    break;
   278 	case SEC_OID_DES_CBC:
   279 	    return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
   280 	case SEC_OID_RC2_CBC:
   281 	    switch(keyLen) {
   282 		case 40:
   283 		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
   284 		case 128:
   285 		case 0:
   286 		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
   287 		default:
   288 		    break;
   289 	    }
   290 	    break;
   291 	case SEC_OID_RC4:
   292 	    switch(keyLen) {
   293 		case 40:
   294 		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
   295 		case 128:
   296 		case 0:
   297 		    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
   298 		default:
   299 		    break;
   300 	    }
   301 	    break;
   302 	default:
   303 	    return sec_pkcs5v2_get_pbe(algTag);
   304     }
   306     return SEC_OID_UNKNOWN;
   307 }
   309 /*
   310  * get the key length in bytes from a PKCS5 PBE
   311  */
   312 int
   313 sec_pkcs5v2_key_length(SECAlgorithmID *algid)
   314 {
   315     SECOidTag algorithm;
   316     PLArenaPool *arena = NULL;
   317     SEC_PKCS5PBEParameter p5_param;
   318     SECStatus rv;
   319     int length = -1;
   321     algorithm = SECOID_GetAlgorithmTag(algid);
   322     /* sanity check, they should all be PBKDF2 here */
   323     if (algorithm != SEC_OID_PKCS5_PBKDF2) {
   324 	return -1;
   325     }
   327     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   328     if (arena == NULL) {
   329 	goto loser;
   330     }
   331     PORT_Memset(&p5_param, 0, sizeof(p5_param));
   332     rv = SEC_ASN1DecodeItem(arena,&p5_param,
   333 			 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
   334     if (rv != SECSuccess) {
   335 	goto loser;
   336     }
   338     if (p5_param.keyLength.data != NULL) {
   339         length = DER_GetInteger(&p5_param.keyLength);
   340     }
   342 loser:
   343     if (arena) {
   344 	PORT_FreeArena(arena, PR_FALSE);
   345     }
   346     return length;
   347 }
   349 /*
   350  *  get the key length in bytes needed for the PBE algorithm
   351  */
   352 int 
   353 SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
   354 {
   356     SECOidTag algorithm;
   358     if(algid == NULL)
   359 	return SEC_OID_UNKNOWN;
   361     algorithm = SECOID_GetAlgorithmTag(algid);
   363     switch(algorithm)
   364     {
   365 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
   366 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
   367 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
   368 	    return 24;
   369 	case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
   370 	case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
   371 	case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
   372 	    return 8;
   373 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   374 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
   375 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
   376 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   377 	    return 5;
   378 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   379 	case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
   380 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   381 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
   382 	    return 16;
   383 	case SEC_OID_PKCS5_PBKDF2:
   384 	    return sec_pkcs5v2_key_length(algid);
   385 	case SEC_OID_PKCS5_PBES2:
   386 	case SEC_OID_PKCS5_PBMAC1:
   387 	    {
   388 		sec_pkcs5V2Parameter *pbeV2_param;
   389 		int length = -1;
   390 		pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
   391 		if (pbeV2_param != NULL) {
   392 	    	    length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId);
   393 		    sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
   394 		}
   395 		return length;
   396 	    }
   398 	default:
   399 	    break;
   400     }
   401     return -1;
   402 }
   405 /* the PKCS12 V2 algorithms only encode the salt, there is no iteration
   406  * count so we need a check for V2 algorithm parameters.
   407  */
   408 static PRBool
   409 sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
   410 {
   411     switch(algorithm) 
   412     {
   413 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
   414 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
   415 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
   416 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
   417 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
   418 	case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
   419 	    return PR_TRUE;
   420 	default:
   421 	    break;
   422     }
   424     return PR_FALSE;
   425 }
   427 static PRBool
   428 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm)
   429 {
   430     switch(algorithm) 
   431     {
   432 	case SEC_OID_PKCS5_PBES2:
   433 	case SEC_OID_PKCS5_PBMAC1:
   434 	case SEC_OID_PKCS5_PBKDF2:
   435 	    return PR_TRUE;
   436 	default:
   437 	    break;
   438     }
   440     return PR_FALSE;
   441 }
   443 /* destroy a pbe parameter.  it assumes that the parameter was 
   444  * generated using the appropriate create function and therefor
   445  * contains an arena pool.
   446  */
   447 static void 
   448 sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
   449 {
   450     if(pbe_param != NULL)
   451 	PORT_FreeArena(pbe_param->poolp, PR_TRUE);
   452 }
   454 /* creates a PBE parameter based on the PBE algorithm.  the only required
   455  * parameters are algorithm and interation.  the return is a PBE parameter
   456  * which conforms to PKCS 5 parameter unless an extended parameter is needed.
   457  * this is primarily if keyLength and a variable key length algorithm are
   458  * specified.
   459  *   salt -  if null, a salt will be generated from random bytes.
   460  *   iteration - number of iterations to perform hashing.
   461  *   keyLength - only used in variable key length algorithms. if specified,
   462  *            should be in bytes.
   463  * once a parameter is allocated, it should be destroyed calling 
   464  * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
   465  */
   466 #define DEFAULT_SALT_LENGTH 16
   467 static SEC_PKCS5PBEParameter *
   468 sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, 
   469 			SECItem *salt, 
   470 			int iteration,
   471 			int keyLength,
   472 			SECOidTag prfAlg)
   473 {
   474     PLArenaPool *poolp = NULL;
   475     SEC_PKCS5PBEParameter *pbe_param = NULL;
   476     SECStatus rv= SECSuccess; 
   477     void *dummy = NULL;
   479     if(iteration < 0) {
   480 	return NULL;
   481     }
   483     poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   484     if(poolp == NULL)
   485 	return NULL;
   487     pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
   488 	sizeof(SEC_PKCS5PBEParameter));
   489     if(!pbe_param) {
   490 	PORT_FreeArena(poolp, PR_TRUE);
   491 	return NULL;
   492     }
   494     pbe_param->poolp = poolp;
   496     rv = SECFailure;
   497     if (salt && salt->data) {
   498     	rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
   499     } else {
   500 	/* sigh, the old interface generated salt on the fly, so we have to
   501 	 * preserve the semantics */
   502 	pbe_param->salt.len = DEFAULT_SALT_LENGTH;
   503 	pbe_param->salt.data = PORT_ArenaZAlloc(poolp,DEFAULT_SALT_LENGTH);
   504 	if (pbe_param->salt.data) {
   505 	   rv = PK11_GenerateRandom(pbe_param->salt.data,DEFAULT_SALT_LENGTH);
   506 	}
   507     }
   509     if(rv != SECSuccess) {
   510 	PORT_FreeArena(poolp, PR_TRUE);
   511 	return NULL;
   512     }
   514     /* encode the integer */
   515     dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, 
   516 		iteration);
   517     rv = (dummy) ? SECSuccess : SECFailure;
   519     if(rv != SECSuccess) {
   520 	PORT_FreeArena(poolp, PR_FALSE);
   521 	return NULL;
   522     }
   524     /*
   525      * for PKCS5 v2 Add the keylength and the prf
   526      */
   527     if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   528 	dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength, 
   529 		keyLength);
   530 	rv = (dummy) ? SECSuccess : SECFailure;
   531 	if (rv != SECSuccess) {
   532 	    PORT_FreeArena(poolp, PR_FALSE);
   533 	    return NULL;
   534 	}
   535 	rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL);
   536 	if (rv != SECSuccess) {
   537 	    PORT_FreeArena(poolp, PR_FALSE);
   538 	    return NULL;
   539 	}
   540 	pbe_param->pPrfAlgId = &pbe_param->prfAlgId;
   541     }
   543     return pbe_param;
   544 }
   546 /* creates a algorithm ID containing the PBE algorithm and appropriate
   547  * parameters.  the required parameter is the algorithm.  if salt is
   548  * not specified, it is generated randomly.  
   549  *
   550  * the returned SECAlgorithmID should be destroyed using 
   551  * SECOID_DestroyAlgorithmID
   552  */
   553 SECAlgorithmID *
   554 sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, 
   555 			   SECOidTag cipherAlgorithm,
   556 			   SECOidTag prfAlg,
   557 			   SECOidTag *pPbeAlgorithm,
   558 			   int keyLength,
   559 			   SECItem *salt, 
   560 			   int iteration)
   561 {
   562     PLArenaPool *poolp = NULL;
   563     SECAlgorithmID *algid, *ret_algid = NULL;
   564     SECOidTag pbeAlgorithm = algorithm;
   565     SECItem der_param;
   566     void *dummy;
   567     SECStatus rv = SECFailure;
   568     SEC_PKCS5PBEParameter *pbe_param = NULL;
   569     sec_pkcs5V2Parameter pbeV2_param;
   571     if(iteration <= 0) {
   572 	return NULL;
   573     }
   575     poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   576     if(!poolp) {
   577 	goto loser;
   578     }
   580     if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) ||
   581     	 	sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
   582 	/* use PKCS 5 v2 */
   583 	SECItem *cipherParams;
   585 	/*
   586 	 * if we ask for pkcs5 Algorithms directly, then the
   587 	 * application needs to supply the cipher algorithm,
   588 	 * otherwise we are implicitly using pkcs5 v2 and the
   589 	 * passed in algorithm is the encryption algorithm.
   590 	 */
   591 	if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
   592 	    if (cipherAlgorithm == SEC_OID_UNKNOWN) {
   593 		goto loser;
   594 	    }
   595 	} else {
   596 	    cipherAlgorithm = algorithm;
   597 	    /* force algorithm to be chosen below */
   598 	    algorithm = SEC_OID_PKCS5_PBKDF2;
   599 	}
   601 	pbeAlgorithm = SEC_OID_PKCS5_PBKDF2;
   602 	/*
   603 	 * 'algorithm' is the overall algorithm oid tag used to wrap the 
   604 	 * entire algoithm ID block. For PKCS5v1 and PKCS12, this 
   605 	 * algorithm OID has encoded in it both the PBE KDF function 
   606 	 * and the encryption algorithm. For PKCS 5v2, PBE KDF and
   607 	 * encryption/macing oids are encoded as parameters in
   608 	 * the algorithm ID block. 
   609 	 *
   610 	 * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11
   611 	 * mechanism, where as in PKCS 5v2, this alogithm tag does not map
   612 	 * directly to a PKCS #11 mechanim, instead the 2 oids in the 
   613 	 * algorithm ID block map the the actual PKCS #11 mechanism.
   614 	 * gorithm is). We use choose this algorithm oid based on the 
   615 	 * cipherAlgorithm to determine what this should be (MAC1 or PBES2).
   616 	 */
   617 	if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   618 	     /* choose mac or pbes */
   619 	     algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
   620 	}
   622 	/* set the PKCS5v2 specific parameters */
   623 	if (keyLength == 0) {
   624 	    SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
   625     	    if (hashAlg != SEC_OID_UNKNOWN) {
   626 	        keyLength = HASH_ResultLenByOidTag(hashAlg);
   627 	    } else {
   628 		CK_MECHANISM_TYPE cryptoMech;
   629 		cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm);
   630 		if (cryptoMech == CKM_INVALID_MECHANISM) {
   631 		    goto loser;
   632 		}
   633 	        keyLength = PK11_GetMaxKeyLength(cryptoMech);
   634 	    }
   635 	    if (keyLength == 0) {
   636 		goto loser;
   637 	    }
   638 	}
   639 	/* currently only SEC_OID_HMAC_SHA1 is defined */
   640 	if (prfAlg == SEC_OID_UNKNOWN) {
   641 	    prfAlg = SEC_OID_HMAC_SHA1;
   642 	}
   644 	/* build the PKCS5v2 cipher algorithm id */
   645 	cipherParams = pk11_GenerateNewParamWithKeyLen(	
   646 			PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
   647 	if (!cipherParams) {
   648 	    goto loser;
   649 	}
   651 	PORT_Memset(&pbeV2_param, 0, sizeof (pbeV2_param));
   653 	rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams, 
   654 				poolp, &pbeV2_param.cipherAlgId);
   655 	SECITEM_FreeItem(cipherParams, PR_TRUE);
   656 	if (rv != SECSuccess) {
   657 	    goto loser;
   658 	}
   659     }
   662     /* generate the parameter */
   663     pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration,
   664 			keyLength, prfAlg);
   665     if(!pbe_param) {
   666 	goto loser;
   667     }
   669     /* generate the algorithm id */
   670     algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
   671     if(algid == NULL) {
   672 	goto loser;
   673     }
   675     der_param.data = NULL;
   676     der_param.len = 0;
   677     if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
   678 	/* first encode the PBE algorithm ID */
   679 	dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
   680 					SEC_PKCS5V2PBEParameterTemplate);
   681 	if (dummy == NULL) {
   682 	    goto loser;
   683 	}
   684 	rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId, 
   685 				   pbeAlgorithm, &der_param);
   686 	if (rv != SECSuccess) {
   687 	    goto loser;
   688 	}
   690 	/* now encode the Full PKCS 5 parameter */
   691 	der_param.data = NULL;
   692 	der_param.len = 0;
   693 	dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param,
   694 					SEC_PKCS5V2ParameterTemplate);
   695     } else if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
   696 	dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
   697 					SEC_PKCS5PBEParameterTemplate);
   698     } else {
   699 	dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
   700 	    				SEC_V2PKCS12PBEParameterTemplate);
   701     }
   702     if (dummy == NULL) {
   703 	goto loser;
   704     }
   706     rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
   707     if (rv != SECSuccess) {
   708 	goto loser;
   709     }
   711     ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
   712     if (ret_algid == NULL) {
   713 	goto loser;
   714     }
   716     rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
   717     if (rv != SECSuccess) {
   718 	SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
   719 	ret_algid = NULL;
   720     } else if (pPbeAlgorithm) {
   721 	*pPbeAlgorithm = pbeAlgorithm;
   722     }
   724 loser:
   725     if (poolp != NULL) {
   726 	PORT_FreeArena(poolp, PR_TRUE);
   727 	algid = NULL;
   728     }
   730     if (pbe_param) {
   731 	sec_pkcs5_destroy_pbe_param(pbe_param);
   732     }
   734     return ret_algid;
   735 }
   737 SECStatus
   738 pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech)
   739 {
   740     SEC_PKCS5PBEParameter p5_param;
   741     SECItem *salt = NULL;
   742     SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
   743     PLArenaPool *arena = NULL;
   744     SECStatus rv = SECFailure;
   745     unsigned char *paramData = NULL;
   746     unsigned char *pSalt = NULL;
   747     CK_ULONG iterations;
   748     int paramLen = 0;
   749     int iv_len;
   752     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   753     if (arena == NULL) {
   754 	goto loser;
   755     }
   758     /*
   759      * decode the algid based on the pbe type
   760      */
   761     PORT_Memset(&p5_param, 0, sizeof(p5_param));
   762     if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
   763         iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
   764         rv = SEC_ASN1DecodeItem(arena, &p5_param,
   765 			 SEC_V2PKCS12PBEParameterTemplate, &algid->parameters);
   766     } else if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   767 	iv_len = 0;
   768         rv = SEC_ASN1DecodeItem(arena,&p5_param,
   769 			 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
   770     } else {
   771         iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
   772         rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate, 
   773 						&algid->parameters);
   774     }
   776     if (iv_len < 0) {
   777 	goto loser;
   778     }
   780     if (rv != SECSuccess) {
   781 	goto loser;
   782     }
   784     /* get salt */
   785     salt = &p5_param.salt;
   786     iterations = (CK_ULONG) DER_GetInteger(&p5_param.iteration);
   788     /* allocate and fill in the PKCS #11 parameters
   789      * based on the algorithm. */
   790     if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   791 	SECOidTag prfAlgTag;
   792     	CK_PKCS5_PBKD2_PARAMS *pbeV2_params = 
   793 		(CK_PKCS5_PBKD2_PARAMS *)PORT_ZAlloc(
   794 			sizeof(CK_PKCS5_PBKD2_PARAMS)+ salt->len);
   796 	if (pbeV2_params == NULL) {
   797 	    goto loser;
   798 	}
   799 	paramData = (unsigned char *)pbeV2_params;
   800 	paramLen = sizeof(CK_PKCS5_PBKD2_PARAMS);
   802 	/* set the prf */
   803 	prfAlgTag = SEC_OID_HMAC_SHA1;
   804  	if (p5_param.pPrfAlgId &&
   805  	    p5_param.pPrfAlgId->algorithm.data != 0) {
   806  	    prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId);
   807 	}
   808 	if (prfAlgTag == SEC_OID_HMAC_SHA1) {
   809 	    pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
   810 	} else {
   811 	    /* only SHA1_HMAC is currently supported by PKCS #11 */
   812 	    PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   813 	    goto loser;
   814 	}
   816 	/* probably should fetch these from the prfAlgid */
   817 	pbeV2_params->pPrfData = NULL;
   818 	pbeV2_params->ulPrfDataLen = 0;
   819 	pbeV2_params->saltSource = CKZ_SALT_SPECIFIED;
   820 	pSalt = ((CK_CHAR_PTR) pbeV2_params)+sizeof(CK_PKCS5_PBKD2_PARAMS);
   821         PORT_Memcpy(pSalt, salt->data, salt->len);
   822 	pbeV2_params->pSaltSourceData = pSalt;
   823 	pbeV2_params->ulSaltSourceDataLen = salt->len;
   824 	pbeV2_params->iterations = iterations;
   825     } else {
   826 	CK_PBE_PARAMS *pbe_params = NULL;
   827     	pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+
   828 						salt->len+iv_len);
   829 	if (pbe_params == NULL) {
   830 	    goto loser;
   831 	}
   832 	paramData = (unsigned char *)pbe_params;
   833 	paramLen = sizeof(CK_PBE_PARAMS);
   835 	pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS);
   836     	pbe_params->pSalt = pSalt;
   837         PORT_Memcpy(pSalt, salt->data, salt->len);
   838 	pbe_params->ulSaltLen = salt->len;
   839 	if (iv_len) {
   840 	    pbe_params->pInitVector = 
   841 		((CK_CHAR_PTR) pbe_params)+ sizeof(CK_PBE_PARAMS)+salt->len;
   842 	}
   843 	pbe_params->ulIteration = iterations;
   844     }
   846     /* copy into the mechanism sec item */
   847     mech->data = paramData;
   848     mech->len = paramLen;
   849     if (arena) {
   850 	PORT_FreeArena(arena,PR_TRUE);
   851     }
   852     return SECSuccess;
   854 loser:
   855     if (paramData) {
   856 	PORT_Free(paramData);
   857     }
   858     if (arena) {
   859 	PORT_FreeArena(arena,PR_TRUE);
   860     }
   861     return SECFailure;
   862 }
   864 /*
   865  * public, deprecated, not valid for pkcs5 v2 
   866  * 
   867  * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create
   868  * PBE algorithmID's directly.
   869  */
   870 SECStatus
   871 PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena,
   872 		     SECAlgorithmID *algId)
   873 {
   874     CK_PBE_PARAMS *pbe_param;
   875     SECItem pbeSalt;
   876     SECAlgorithmID *pbeAlgID = NULL;
   877     SECStatus rv;
   879     if(!param || !algId) {
   880 	return SECFailure;
   881     }
   883     pbe_param = (CK_PBE_PARAMS *)param->data;
   884     pbeSalt.data = (unsigned char *)pbe_param->pSalt;
   885     pbeSalt.len = pbe_param->ulSaltLen;
   886     pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, 
   887 	SEC_OID_UNKNOWN, NULL, 0, &pbeSalt, (int)pbe_param->ulIteration);
   888     if(!pbeAlgID) {
   889 	return SECFailure;
   890     }
   892     rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
   893     SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
   894     return rv;
   895 }
   897 /*
   898  * public, Deprecated, This function is only for binary compatibility with 
   899  * older applications. Does not support PKCS5v2.
   900  *
   901  * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
   902  * iv values rather than generating PBE bits directly.
   903  */
   904 PBEBitGenContext *
   905 PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
   906 	SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
   907 	unsigned int iterations)
   908 {
   909     SECItem *context = NULL;
   910     SECItem mechItem;
   911     CK_PBE_PARAMS pbe_params;
   912     CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
   913     PK11SlotInfo *slot;
   914     PK11SymKey *symKey = NULL;
   915     unsigned char ivData[8];
   918     /* use the purpose to select the low level keygen algorithm */
   919     switch (bitGenPurpose) {
   920     case pbeBitGenIntegrityKey:
   921 	switch (hashAlgorithm) {
   922 	case SEC_OID_SHA1:
   923 	    mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC;
   924 	    break;
   925 	case SEC_OID_MD2:
   926 	    mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN;
   927 	    break;
   928 	case SEC_OID_MD5:
   929 	    mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN;
   930 	    break;
   931 	default:
   932 	    break;
   933 	}
   934 	break;
   935     case pbeBitGenCipherIV:
   936 	if (bitsNeeded > 64) {
   937 	    break;
   938 	}
   939 	if (hashAlgorithm != SEC_OID_SHA1) {
   940 	    break;
   941 	}
   942 	mechanism = CKM_PBE_SHA1_DES3_EDE_CBC;
   943 	break;
   944     case pbeBitGenCipherKey:
   945 	if (hashAlgorithm != SEC_OID_SHA1) {
   946 	    break;
   947 	}
   948 	switch (bitsNeeded) {
   949 	case 40:
   950 	    mechanism = CKM_PBE_SHA1_RC4_40;
   951 	    break;
   952 	case 128:
   953 	    mechanism = CKM_PBE_SHA1_RC4_128;
   954 	    break;
   955 	default:
   956 	    break;
   957 	}
   958     case pbeBitGenIDNull:
   959 	break;
   960     }
   962     if (mechanism == CKM_INVALID_MECHANISM) {
   963 	/* we should set an error, but this is a deprecated function, and
   964 	 * we are keeping bug for bug compatibility;)... */
   965 	    return NULL;
   966     } 
   968     pbe_params.pInitVector = ivData;
   969     pbe_params.pPassword = pwitem->data;
   970     pbe_params.ulPasswordLen = pwitem->len;
   971     pbe_params.pSalt = salt->data;
   972     pbe_params.ulSaltLen = salt->len;
   973     pbe_params.ulIteration = iterations;
   974     mechItem.data = (unsigned char *) &pbe_params;
   975     mechItem.len = sizeof(pbe_params);
   978     slot = PK11_GetInternalSlot();
   979     symKey = PK11_RawPBEKeyGen(slot,mechanism,
   980 					&mechItem, pwitem, PR_FALSE, NULL);
   981     PK11_FreeSlot(slot);
   982     if (symKey != NULL) {
   983 	if (bitGenPurpose == pbeBitGenCipherIV) {
   984 	    /* NOTE: this assumes that bitsNeeded is a multiple of 8! */
   985 	    SECItem ivItem;
   987 	    ivItem.data = ivData;
   988 	    ivItem.len = bitsNeeded/8;
   989 	    context = SECITEM_DupItem(&ivItem);
   990 	} else {
   991 	    SECItem *keyData;
   992 	    PK11_ExtractKeyValue(symKey);
   993 	    keyData = PK11_GetKeyData(symKey);
   995 	    /* assert bitsNeeded with length? */
   996 	    if (keyData) {
   997 	    	context = SECITEM_DupItem(keyData);
   998 	    }
   999 	}
  1000 	PK11_FreeSymKey(symKey);
  1003     return (PBEBitGenContext *)context;
  1006 /*
  1007  * public, Deprecated, This function is only for binary compatibility with 
  1008  * older applications. Does not support PKCS5v2.
  1010  * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for
  1011  * iv values rather than generating PBE bits directly.
  1012  */
  1013 SECItem *
  1014 PBE_GenerateBits(PBEBitGenContext *context)
  1016     return (SECItem *)context;
  1019 /*
  1020  * public, Deprecated, This function is only for binary compatibility with 
  1021  * older applications. Does not support PKCS5v2.
  1023  * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
  1024  * iv values rather than generating PBE bits directly.
  1025  */
  1026 void
  1027 PBE_DestroyContext(PBEBitGenContext *context)
  1029     SECITEM_FreeItem((SECItem *)context,PR_TRUE);
  1032 /*
  1033  * public, deprecated. Replaced with PK11_GetPBEIV().
  1034  */
  1035 SECItem *
  1036 SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
  1038     /* pbe stuff */
  1039     CK_MECHANISM_TYPE type;
  1040     SECItem *param = NULL;
  1041     SECItem *iv = NULL;
  1042     SECItem src;
  1043     int iv_len = 0;
  1044     PK11SymKey *symKey;
  1045     PK11SlotInfo *slot;
  1046     CK_PBE_PARAMS_PTR pPBEparams;
  1047     SECOidTag	pbeAlg;
  1049     pbeAlg = SECOID_GetAlgorithmTag(algid);
  1050     if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
  1051 	unsigned char *ivData;
  1052 	sec_pkcs5V2Parameter *pbeV2_param = NULL;
  1054 	/* can only return the IV if the crypto Algorithm exists */
  1055 	if (pbeAlg == SEC_OID_PKCS5_PBKDF2) {
  1056 	    PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1057 	    goto loser;
  1059 	pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
  1060 	if (pbeV2_param == NULL) {
  1061 	    goto loser;
  1063 	/* extract the IV from the cipher algid portion of our pkcs 5 v2
  1064 	 * algorithm id */
  1065     	type = PK11_AlgtagToMechanism(
  1066     		SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
  1067 	param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId);
  1068 	sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
  1069 	if (!param) {
  1070 	    goto loser;
  1072 	/* NOTE: NULL is a permissible return here */
  1073 	ivData = PK11_IVFromParam(type, param, &iv_len);
  1074 	src.data = ivData;
  1075 	src.len = iv_len;
  1076 	goto done;
  1079     type = PK11_AlgtagToMechanism(pbeAlg);
  1080     param = PK11_ParamFromAlgid(algid);
  1081     if (param == NULL) {
  1082 	goto done;
  1084     slot = PK11_GetInternalSlot();
  1085     symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL);
  1086     PK11_FreeSlot(slot);
  1087     if (symKey == NULL) {
  1088 	goto loser;
  1090     PK11_FreeSymKey(symKey);
  1091     pPBEparams = (CK_PBE_PARAMS_PTR)param->data;
  1092     iv_len = PK11_GetIVLength(type);
  1094     src.data = (unsigned char *)pPBEparams->pInitVector;
  1095     src.len = iv_len;
  1097 done:
  1098     iv = SECITEM_DupItem(&src);
  1100 loser:
  1101     if (param) {
  1102 	SECITEM_ZfreeItem(param, PR_TRUE);
  1104     return iv;
  1107 /*
  1108  * Subs from nss 3.x that are deprecated
  1109  */
  1110 PBEBitGenContext *
  1111 __PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
  1112 	SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
  1113 	unsigned int iterations)
  1115     PORT_Assert("__PBE_CreateContext is Deprecated" == NULL);
  1116     return NULL;
  1119 SECItem *
  1120 __PBE_GenerateBits(PBEBitGenContext *context)
  1122     PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL);
  1123     return NULL;
  1126 void
  1127 __PBE_DestroyContext(PBEBitGenContext *context)
  1129     PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL);
  1132 SECStatus
  1133 RSA_FormatBlock(SECItem *result, unsigned modulusLen,
  1134                 int blockType, SECItem *data)
  1136     PORT_Assert("RSA_FormatBlock is Deprecated" == NULL);
  1137     return SECFailure;
  1140 /****************************************************************************
  1142  * Now Do The PBE Functions Here...
  1144  ****************************************************************************/
  1146 static void
  1147 pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
  1149     if (pbe_params) {
  1150 	if (pbe_params->pPassword)
  1151 	    PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen);
  1152 	if (pbe_params->pSalt)
  1153 	    PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen);
  1154 	PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS));
  1158 /*
  1159  * public, deprecated.  use PK11_CreatePBEAlgorithmID or 
  1160  * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters, 
  1161  * use PK11_ParamFromAlgid from the algorithm id you created using 
  1162  * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID.
  1163  */
  1164 SECItem * 
  1165 PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
  1167     CK_PBE_PARAMS *pbe_params = NULL;
  1168     SECItem *paramRV = NULL;
  1170     paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
  1171     if (!paramRV ) {
  1172 	goto loser;
  1174     /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */
  1175     PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS));
  1177     pbe_params = (CK_PBE_PARAMS *)paramRV->data;
  1178     pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
  1179     if (!pbe_params->pPassword) {
  1180         goto loser;
  1182     PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
  1183     pbe_params->ulPasswordLen = pwd->len;
  1185     pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
  1186     if (!pbe_params->pSalt) {
  1187 	goto loser;
  1189     PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
  1190     pbe_params->ulSaltLen = salt->len;
  1192     pbe_params->ulIteration = (CK_ULONG)iterations;
  1193     return paramRV;
  1195 loser:
  1196     if (pbe_params)
  1197         pk11_destroy_ck_pbe_params(pbe_params);
  1198     if (paramRV) 
  1199     	PORT_ZFree(paramRV, sizeof(SECItem));
  1200     return NULL;
  1203 /*
  1204  * public, deprecated.
  1205  */
  1206 void
  1207 PK11_DestroyPBEParams(SECItem *pItem)
  1209     if (pItem) {
  1210 	CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data);
  1211 	if (params)
  1212 	    pk11_destroy_ck_pbe_params(params);
  1213 	PORT_ZFree(pItem, sizeof(SECItem));
  1217 /*
  1218  * public, Partially supports PKCS5 V2 (some parameters are not controllable
  1219  * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need
  1220  * finer control these.
  1221  */
  1222 SECAlgorithmID *
  1223 PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
  1225     SECAlgorithmID *algid = NULL;
  1226     algid = sec_pkcs5CreateAlgorithmID(algorithm,
  1227 		 SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL, 0, salt, iteration);
  1228     return algid;
  1231 /*
  1232  * public, fully support pkcs5v2.
  1233  */
  1234 SECAlgorithmID *
  1235 PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag,
  1236 			    SECOidTag prfAlgTag, int keyLength, int iteration, 
  1237 			    SECItem *salt)
  1239     SECAlgorithmID *algid = NULL;
  1240     algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag,
  1241 					NULL, keyLength, salt, iteration);
  1242     return algid;
  1245 /*
  1246  * private.
  1247  */
  1248 PK11SymKey *
  1249 pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 
  1250 			SECItem *params, CK_KEY_TYPE keyType, int keyLen,
  1251 			SECItem *pwitem, void *wincx)
  1253     CK_ULONG pwLen;
  1254     /* do some sanity checks */
  1255     if ((params == NULL) || (params->data == NULL)) {
  1256 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1257 	return NULL;
  1260     if (type == CKM_INVALID_MECHANISM) {
  1261 	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1262 	return NULL;
  1265     /* set the password pointer in the parameters... */
  1266     if (type == CKM_PKCS5_PBKD2) {
  1267     	CK_PKCS5_PBKD2_PARAMS *pbev2_params;
  1268 	if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) {
  1269 	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1270 	    return NULL;
  1272 	pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data;
  1273 	pbev2_params->pPassword = pwitem->data;
  1274 	pwLen = pwitem->len;
  1275 	pbev2_params->ulPasswordLen = &pwLen;
  1276     } else {
  1277     	CK_PBE_PARAMS *pbe_params;
  1278 	if (params->len < sizeof(CK_PBE_PARAMS)) {
  1279 	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1280 	    return NULL;
  1282 	pbe_params = (CK_PBE_PARAMS *)params->data;
  1283 	pbe_params->pPassword = pwitem->data;
  1284 	pbe_params->ulPasswordLen = pwitem->len;
  1287     /* generate the key (and sometimes the IV as a side effect...) */
  1288     return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType, 
  1289 	   keyLen, NULL, CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP, 
  1290 	   0, wincx);
  1293 /*
  1294  * public, deprecated. use PK11_PBEKeyGen instead.
  1295  */
  1296 PK11SymKey *
  1297 PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech,
  1298 			 SECItem *pwitem, PRBool faulty3DES, void *wincx)
  1300     if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
  1301 	type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
  1303     return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx);
  1306 /*
  1307  * pubic, supports pkcs5 v2.
  1309  * Create symkey from a PBE key. The algid can be created with
  1310  *  PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by
  1311  *  extraction of der data.
  1312  */
  1313 PK11SymKey *
  1314 PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
  1315 	       					PRBool faulty3DES, void *wincx)
  1317     CK_MECHANISM_TYPE type;
  1318     SECItem *param = NULL;
  1319     PK11SymKey *symKey = NULL;
  1320     SECOidTag	pbeAlg;
  1321     CK_KEY_TYPE keyType = -1;
  1322     int keyLen = 0;
  1324     pbeAlg = SECOID_GetAlgorithmTag(algid);
  1325     /* if we're using PKCS5v2, extract the additional information we need
  1326      * (key length, key type, and pbeAlg). */
  1327     if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
  1328 	CK_MECHANISM_TYPE cipherMech;
  1329 	sec_pkcs5V2Parameter *pbeV2_param;
  1331 	pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
  1332 	if (pbeV2_param == NULL) {
  1333 	    return NULL;
  1335 	cipherMech = PK11_AlgtagToMechanism(
  1336 		SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
  1337 	pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
  1338 	param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId);
  1339 	sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
  1340 	keyLen = SEC_PKCS5GetKeyLength(algid);
  1341 	if (keyLen == -1) {
  1342 	    keyLen = 0;
  1344 	keyType = PK11_GetKeyType(cipherMech, keyLen);
  1345     } else {
  1346 	param = PK11_ParamFromAlgid(algid);
  1349     if(param == NULL) {
  1350 	goto loser;
  1353     type = PK11_AlgtagToMechanism(pbeAlg);	
  1354     if (type == CKM_INVALID_MECHANISM) {
  1355 	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1356 	goto loser;
  1358     if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
  1359 	type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
  1361     symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen, 
  1362 					pwitem, wincx);
  1364 loser:
  1365     if (param) {
  1366 	SECITEM_ZfreeItem(param, PR_TRUE);
  1368     return symKey;
  1371 /*
  1372  * public, supports pkcs5v2
  1373  */
  1374 SECItem *
  1375 PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem)
  1377     return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE);
  1380 CK_MECHANISM_TYPE
  1381 pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, 
  1382 			   SECItem *pbe_pwd, PRBool faulty3DES)
  1384     int keyLen = 0;
  1385     SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid);
  1386     CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag);
  1387     CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM;
  1388     SECItem *iv = NULL;
  1390     if (mech == CKM_INVALID_MECHANISM) {
  1391 	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1392 	goto loser;
  1394     if (PK11_GetIVLength(mech)) {
  1395 	iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES);
  1396 	if (iv == NULL) {
  1397 	    goto loser;
  1401     keyLen = SEC_PKCS5GetKeyLength(algid);
  1403     *param = pk11_ParamFromIVWithLen(mech, iv, keyLen);
  1404     if (*param == NULL) {
  1405 	goto loser;
  1407     returnedMechanism = mech;
  1409 loser:
  1410     if (iv) {
  1411 	SECITEM_FreeItem(iv,PR_TRUE);
  1413     return returnedMechanism;
  1416 /*
  1417  * Public, supports pkcs5 v2
  1419  * Get the crypto mechanism directly from the pbe algorithmid.
  1421  * It's important to go directly from the algorithm id so that we can
  1422  * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases.
  1424  * This function returns both the mechanism and the parameter for the mechanism.
  1425  * The caller is responsible for freeing the parameter.
  1426  */
  1427 CK_MECHANISM_TYPE
  1428 PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, 
  1429 			   SECItem *pbe_pwd)
  1431     return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE);

mercurial