xref: /onnv-gate/usr/src/common/openssl/crypto/asn1/p5_pbev2.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* p5_pbev2.c */
20Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3*2139Sjp161948  * project 1999-2004.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate /* ====================================================================
60Sstevel@tonic-gate  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
90Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
100Sstevel@tonic-gate  * are met:
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
130Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
160Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
170Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
180Sstevel@tonic-gate  *    distribution.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
210Sstevel@tonic-gate  *    software must display the following acknowledgment:
220Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
230Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
260Sstevel@tonic-gate  *    endorse or promote products derived from this software without
270Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
280Sstevel@tonic-gate  *    licensing@OpenSSL.org.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
310Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
320Sstevel@tonic-gate  *    permission of the OpenSSL Project.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
350Sstevel@tonic-gate  *    acknowledgment:
360Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
370Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
400Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
410Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
420Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
430Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
440Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
450Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
460Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
470Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
480Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
490Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
500Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
510Sstevel@tonic-gate  * ====================================================================
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
540Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
550Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include "cryptlib.h"
610Sstevel@tonic-gate #include <openssl/asn1t.h>
620Sstevel@tonic-gate #include <openssl/x509.h>
630Sstevel@tonic-gate #include <openssl/rand.h>
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /* PKCS#5 v2.0 password based encryption structures */
660Sstevel@tonic-gate 
670Sstevel@tonic-gate ASN1_SEQUENCE(PBE2PARAM) = {
680Sstevel@tonic-gate 	ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR),
690Sstevel@tonic-gate 	ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR)
700Sstevel@tonic-gate } ASN1_SEQUENCE_END(PBE2PARAM)
710Sstevel@tonic-gate 
720Sstevel@tonic-gate IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM)
730Sstevel@tonic-gate 
740Sstevel@tonic-gate ASN1_SEQUENCE(PBKDF2PARAM) = {
750Sstevel@tonic-gate 	ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY),
760Sstevel@tonic-gate 	ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER),
770Sstevel@tonic-gate 	ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER),
780Sstevel@tonic-gate 	ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR)
790Sstevel@tonic-gate } ASN1_SEQUENCE_END(PBKDF2PARAM)
800Sstevel@tonic-gate 
810Sstevel@tonic-gate IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm:
840Sstevel@tonic-gate  * yes I know this is horrible!
850Sstevel@tonic-gate  */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
880Sstevel@tonic-gate 				 unsigned char *salt, int saltlen)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate 	X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL;
910Sstevel@tonic-gate 	int alg_nid;
920Sstevel@tonic-gate 	EVP_CIPHER_CTX ctx;
930Sstevel@tonic-gate 	unsigned char iv[EVP_MAX_IV_LENGTH];
940Sstevel@tonic-gate 	PBKDF2PARAM *kdf = NULL;
950Sstevel@tonic-gate 	PBE2PARAM *pbe2 = NULL;
960Sstevel@tonic-gate 	ASN1_OCTET_STRING *osalt = NULL;
970Sstevel@tonic-gate 	ASN1_OBJECT *obj;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	alg_nid = EVP_CIPHER_type(cipher);
1000Sstevel@tonic-gate 	if(alg_nid == NID_undef) {
1010Sstevel@tonic-gate 		ASN1err(ASN1_F_PKCS5_PBE2_SET,
1020Sstevel@tonic-gate 				ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
1030Sstevel@tonic-gate 		goto err;
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 	obj = OBJ_nid2obj(alg_nid);
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	if(!(pbe2 = PBE2PARAM_new())) goto merr;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	/* Setup the AlgorithmIdentifier for the encryption scheme */
1100Sstevel@tonic-gate 	scheme = pbe2->encryption;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	scheme->algorithm = obj;
1130Sstevel@tonic-gate 	if(!(scheme->parameter = ASN1_TYPE_new())) goto merr;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	/* Create random IV */
116*2139Sjp161948 	if (EVP_CIPHER_iv_length(cipher) &&
117*2139Sjp161948 		RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0)
118*2139Sjp161948   		goto err;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&ctx);
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	/* Dummy cipherinit to just setup the IV */
1230Sstevel@tonic-gate 	EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0);
1240Sstevel@tonic-gate 	if(EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) {
1250Sstevel@tonic-gate 		ASN1err(ASN1_F_PKCS5_PBE2_SET,
1260Sstevel@tonic-gate 					ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
127*2139Sjp161948 		EVP_CIPHER_CTX_cleanup(&ctx);
1280Sstevel@tonic-gate 		goto err;
1290Sstevel@tonic-gate 	}
1300Sstevel@tonic-gate 	EVP_CIPHER_CTX_cleanup(&ctx);
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	if(!(kdf = PBKDF2PARAM_new())) goto merr;
1330Sstevel@tonic-gate 	if(!(osalt = M_ASN1_OCTET_STRING_new())) goto merr;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	if (!saltlen) saltlen = PKCS5_SALT_LEN;
1360Sstevel@tonic-gate 	if (!(osalt->data = OPENSSL_malloc (saltlen))) goto merr;
1370Sstevel@tonic-gate 	osalt->length = saltlen;
1380Sstevel@tonic-gate 	if (salt) memcpy (osalt->data, salt, saltlen);
1390Sstevel@tonic-gate 	else if (RAND_pseudo_bytes (osalt->data, saltlen) < 0) goto merr;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	if(iter <= 0) iter = PKCS5_DEFAULT_ITER;
1420Sstevel@tonic-gate 	if(!ASN1_INTEGER_set(kdf->iter, iter)) goto merr;
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	/* Now include salt in kdf structure */
1450Sstevel@tonic-gate 	kdf->salt->value.octet_string = osalt;
1460Sstevel@tonic-gate 	kdf->salt->type = V_ASN1_OCTET_STRING;
1470Sstevel@tonic-gate 	osalt = NULL;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/* If its RC2 then we'd better setup the key length */
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	if(alg_nid == NID_rc2_cbc) {
1520Sstevel@tonic-gate 		if(!(kdf->keylength = M_ASN1_INTEGER_new())) goto merr;
1530Sstevel@tonic-gate 		if(!ASN1_INTEGER_set (kdf->keylength,
1540Sstevel@tonic-gate 				 EVP_CIPHER_key_length(cipher))) goto merr;
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	/* prf can stay NULL because we are using hmacWithSHA1 */
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	/* Now setup the PBE2PARAM keyfunc structure */
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	pbe2->keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	/* Encode PBKDF2PARAM into parameter of pbe2 */
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	if(!(pbe2->keyfunc->parameter = ASN1_TYPE_new())) goto merr;
1660Sstevel@tonic-gate 
167*2139Sjp161948 	if(!ASN1_pack_string_of(PBKDF2PARAM, kdf, i2d_PBKDF2PARAM,
1680Sstevel@tonic-gate 			 &pbe2->keyfunc->parameter->value.sequence)) goto merr;
1690Sstevel@tonic-gate 	pbe2->keyfunc->parameter->type = V_ASN1_SEQUENCE;
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	PBKDF2PARAM_free(kdf);
1720Sstevel@tonic-gate 	kdf = NULL;
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 	/* Now set up top level AlgorithmIdentifier */
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if(!(ret = X509_ALGOR_new())) goto merr;
1770Sstevel@tonic-gate 	if(!(ret->parameter = ASN1_TYPE_new())) goto merr;
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	ret->algorithm = OBJ_nid2obj(NID_pbes2);
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	/* Encode PBE2PARAM into parameter */
1820Sstevel@tonic-gate 
183*2139Sjp161948 	if(!ASN1_pack_string_of(PBE2PARAM, pbe2, i2d_PBE2PARAM,
1840Sstevel@tonic-gate 				 &ret->parameter->value.sequence)) goto merr;
1850Sstevel@tonic-gate 	ret->parameter->type = V_ASN1_SEQUENCE;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	PBE2PARAM_free(pbe2);
1880Sstevel@tonic-gate 	pbe2 = NULL;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	return ret;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	merr:
1930Sstevel@tonic-gate 	ASN1err(ASN1_F_PKCS5_PBE2_SET,ERR_R_MALLOC_FAILURE);
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	err:
1960Sstevel@tonic-gate 	PBE2PARAM_free(pbe2);
1970Sstevel@tonic-gate 	/* Note 'scheme' is freed as part of pbe2 */
1980Sstevel@tonic-gate 	M_ASN1_OCTET_STRING_free(osalt);
1990Sstevel@tonic-gate 	PBKDF2PARAM_free(kdf);
2000Sstevel@tonic-gate 	X509_ALGOR_free(kalg);
2010Sstevel@tonic-gate 	X509_ALGOR_free(ret);
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	return NULL;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate }
206