Home | History | Annotate | Download | only in cms
      1 /* crypto/cms/cms_pwri.c */
      2 /* Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL
      3  * project.
      4  */
      5 /* ====================================================================
      6  * Copyright (c) 2009 The OpenSSL Project.  All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in
     17  *    the documentation and/or other materials provided with the
     18  *    distribution.
     19  *
     20  * 3. All advertising materials mentioning features or use of this
     21  *    software must display the following acknowledgment:
     22  *    "This product includes software developed by the OpenSSL Project
     23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     24  *
     25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     26  *    endorse or promote products derived from this software without
     27  *    prior written permission. For written permission, please contact
     28  *    licensing (at) OpenSSL.org.
     29  *
     30  * 5. Products derived from this software may not be called "OpenSSL"
     31  *    nor may "OpenSSL" appear in their names without prior written
     32  *    permission of the OpenSSL Project.
     33  *
     34  * 6. Redistributions of any form whatsoever must retain the following
     35  *    acknowledgment:
     36  *    "This product includes software developed by the OpenSSL Project
     37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     38  *
     39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     50  * OF THE POSSIBILITY OF SUCH DAMAGE.
     51  * ====================================================================
     52  */
     53 
     54 #include "cryptlib.h"
     55 #include <openssl/asn1t.h>
     56 #include <openssl/pem.h>
     57 #include <openssl/x509v3.h>
     58 #include <openssl/err.h>
     59 #include <openssl/cms.h>
     60 #include <openssl/rand.h>
     61 #include <openssl/aes.h>
     62 #include "cms_lcl.h"
     63 #include "asn1_locl.h"
     64 
     65 int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
     66 				unsigned char *pass, ossl_ssize_t passlen)
     67 	{
     68 	CMS_PasswordRecipientInfo *pwri;
     69 	if (ri->type != CMS_RECIPINFO_PASS)
     70 		{
     71 		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD, CMS_R_NOT_PWRI);
     72 		return 0;
     73 		}
     74 
     75 	pwri = ri->d.pwri;
     76 	pwri->pass = pass;
     77 	if (pass && passlen < 0)
     78 		passlen = strlen((char *)pass);
     79 	pwri->passlen = passlen;
     80 	return 1;
     81 	}
     82 
     83 CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
     84 					int iter, int wrap_nid, int pbe_nid,
     85 					unsigned char *pass,
     86 					ossl_ssize_t passlen,
     87 					const EVP_CIPHER *kekciph)
     88 	{
     89 	CMS_RecipientInfo *ri = NULL;
     90 	CMS_EnvelopedData *env;
     91 	CMS_PasswordRecipientInfo *pwri;
     92 	EVP_CIPHER_CTX ctx;
     93 	X509_ALGOR *encalg = NULL;
     94 	unsigned char iv[EVP_MAX_IV_LENGTH];
     95 	int ivlen;
     96 
     97 	env = cms_get0_enveloped(cms);
     98 	if (!env)
     99 		return NULL;
    100 
    101 	if (wrap_nid <= 0)
    102 		wrap_nid = NID_id_alg_PWRI_KEK;
    103 
    104 	if (pbe_nid <= 0)
    105 		pbe_nid = NID_id_pbkdf2;
    106 
    107 	/* Get from enveloped data */
    108 	if (kekciph == NULL)
    109 		kekciph = env->encryptedContentInfo->cipher;
    110 
    111 	if (kekciph == NULL)
    112 		{
    113 		CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER);
    114 		return NULL;
    115 		}
    116 	if (wrap_nid != NID_id_alg_PWRI_KEK)
    117 		{
    118 		CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
    119 				CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
    120 		return NULL;
    121 		}
    122 
    123 	/* Setup algorithm identifier for cipher */
    124 	encalg = X509_ALGOR_new();
    125 	EVP_CIPHER_CTX_init(&ctx);
    126 
    127 	if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0)
    128 		{
    129 		CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
    130 		goto err;
    131 		}
    132 
    133 	ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
    134 
    135 	if (ivlen > 0)
    136 		{
    137 		if (RAND_pseudo_bytes(iv, ivlen) <= 0)
    138 			goto err;
    139 		if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0)
    140 			{
    141 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
    142 							ERR_R_EVP_LIB);
    143 			goto err;
    144 			}
    145 		encalg->parameter = ASN1_TYPE_new();
    146 		if (!encalg->parameter)
    147 			{
    148 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
    149 							ERR_R_MALLOC_FAILURE);
    150 			goto err;
    151 			}
    152 		if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0)
    153 			{
    154 			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD,
    155 				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
    156 			goto err;
    157 			}
    158 		}
    159 
    160 
    161 	encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx));
    162 
    163 	EVP_CIPHER_CTX_cleanup(&ctx);
    164 
    165 	/* Initialize recipient info */
    166 	ri = M_ASN1_new_of(CMS_RecipientInfo);
    167 	if (!ri)
    168 		goto merr;
    169 
    170 	ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
    171 	if (!ri->d.pwri)
    172 		goto merr;
    173 	ri->type = CMS_RECIPINFO_PASS;
    174 
    175 	pwri = ri->d.pwri;
    176 	/* Since this is overwritten, free up empty structure already there */
    177 	X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
    178 	pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
    179 	if (!pwri->keyEncryptionAlgorithm)
    180 		goto merr;
    181 	pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
    182 	pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
    183 	if (!pwri->keyEncryptionAlgorithm->parameter)
    184 		goto merr;
    185 
    186         if(!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR),
    187 	    &pwri->keyEncryptionAlgorithm->parameter->value.sequence))
    188 		goto merr;
    189         pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
    190 
    191 	X509_ALGOR_free(encalg);
    192 	encalg = NULL;
    193 
    194 	/* Setup PBE algorithm */
    195 
    196 	pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
    197 
    198 	if (!pwri->keyDerivationAlgorithm)
    199 		goto err;
    200 
    201 	CMS_RecipientInfo_set0_password(ri, pass, passlen);
    202 	pwri->version = 0;
    203 
    204 	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
    205 		goto merr;
    206 
    207 	return ri;
    208 
    209 	merr:
    210 	CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE);
    211 	err:
    212 	EVP_CIPHER_CTX_cleanup(&ctx);
    213 	if (ri)
    214 		M_ASN1_free_of(ri, CMS_RecipientInfo);
    215 	if (encalg)
    216 		X509_ALGOR_free(encalg);
    217 	return NULL;
    218 
    219 	}
    220 
    221 /* This is an implementation of the key wrapping mechanism in RFC3211,
    222  * at some point this should go into EVP.
    223  */
    224 
    225 static int kek_unwrap_key(unsigned char *out, size_t *outlen,
    226 		const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
    227 	{
    228 	size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
    229 	unsigned char *tmp;
    230 	int outl, rv = 0;
    231 	if (inlen < 2 * blocklen)
    232 		{
    233 		/* too small */
    234 		return 0;
    235 		}
    236 	if (inlen % blocklen)
    237 		{
    238 		/* Invalid size */
    239 		return 0;
    240 		}
    241 	tmp = OPENSSL_malloc(inlen);
    242 	/* setup IV by decrypting last two blocks */
    243 	EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
    244 				in  + inlen - 2 * blocklen, blocklen * 2);
    245 	/* Do a decrypt of last decrypted block to set IV to correct value
    246 	 * output it to start of buffer so we don't corrupt decrypted block
    247 	 * this works because buffer is at least two block lengths long.
    248 	 */
    249 	EVP_DecryptUpdate(ctx, tmp, &outl,
    250 				tmp  + inlen - blocklen, blocklen);
    251 	/* Can now decrypt first n - 1 blocks */
    252 	EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen);
    253 
    254 	/* Reset IV to original value */
    255 	EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL);
    256 	/* Decrypt again */
    257 	EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen);
    258 	/* Check check bytes */
    259 	if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff)
    260 		{
    261 		/* Check byte failure */
    262 		goto err;
    263 		}
    264 	if (inlen < (size_t)(tmp[0] - 4 ))
    265 		{
    266 		/* Invalid length value */
    267 		goto err;
    268 		}
    269 	*outlen = (size_t)tmp[0];
    270 	memcpy(out, tmp + 4, *outlen);
    271 	rv = 1;
    272 	err:
    273 	OPENSSL_cleanse(tmp, inlen);
    274 	OPENSSL_free(tmp);
    275 	return rv;
    276 
    277 	}
    278 
    279 static int kek_wrap_key(unsigned char *out, size_t *outlen,
    280 		const unsigned char *in, size_t inlen, EVP_CIPHER_CTX *ctx)
    281 	{
    282 	size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
    283 	size_t olen;
    284 	int dummy;
    285 	/* First decide length of output buffer: need header and round up to
    286 	 * multiple of block length.
    287 	 */
    288 	olen = (inlen + 4 + blocklen - 1)/blocklen;
    289 	olen *= blocklen;
    290 	if (olen < 2 * blocklen)
    291 		{
    292 		/* Key too small */
    293 		return 0;
    294 		}
    295 	if (inlen > 0xFF)
    296 		{
    297 		/* Key too large */
    298 		return 0;
    299 		}
    300 	if (out)
    301 		{
    302 		/* Set header */
    303 		out[0] = (unsigned char)inlen;
    304 		out[1] = in[0] ^ 0xFF;
    305 		out[2] = in[1] ^ 0xFF;
    306 		out[3] = in[2] ^ 0xFF;
    307 		memcpy(out + 4, in, inlen);
    308 		/* Add random padding to end */
    309 		if (olen > inlen + 4)
    310 			RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen);
    311 		/* Encrypt twice */
    312 		EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
    313 		EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
    314 		}
    315 
    316 	*outlen = olen;
    317 
    318 	return 1;
    319 	}
    320 
    321 /* Encrypt/Decrypt content key in PWRI recipient info */
    322 
    323 int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
    324 							int en_de)
    325 	{
    326 	CMS_EncryptedContentInfo *ec;
    327 	CMS_PasswordRecipientInfo *pwri;
    328 	const unsigned char *p = NULL;
    329 	int plen;
    330 	int r = 0;
    331 	X509_ALGOR *algtmp, *kekalg = NULL;
    332 	EVP_CIPHER_CTX kekctx;
    333 	const EVP_CIPHER *kekcipher;
    334 	unsigned char *key = NULL;
    335 	size_t keylen;
    336 
    337 	ec = cms->d.envelopedData->encryptedContentInfo;
    338 
    339 	pwri = ri->d.pwri;
    340 	EVP_CIPHER_CTX_init(&kekctx);
    341 
    342 	if (!pwri->pass)
    343 		{
    344 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_NO_PASSWORD);
    345 		return 0;
    346 		}
    347 	algtmp = pwri->keyEncryptionAlgorithm;
    348 
    349 	if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK)
    350 		{
    351 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
    352 				CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
    353 		return 0;
    354 		}
    355 
    356 	if (algtmp->parameter->type == V_ASN1_SEQUENCE)
    357 		{
    358 		p = algtmp->parameter->value.sequence->data;
    359 		plen = algtmp->parameter->value.sequence->length;
    360 		kekalg = d2i_X509_ALGOR(NULL, &p, plen);
    361 		}
    362 	if (kekalg == NULL)
    363 		{
    364 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
    365 				CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
    366 		return 0;
    367 		}
    368 
    369 	kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
    370 
    371 	if(!kekcipher)
    372 		{
    373 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
    374 				CMS_R_UNKNOWN_CIPHER);
    375 		goto err;
    376 		}
    377 
    378 	/* Fixup cipher based on AlgorithmIdentifier to set IV etc */
    379 	if (!EVP_CipherInit_ex(&kekctx, kekcipher, NULL, NULL, NULL, en_de))
    380 		goto err;
    381 	EVP_CIPHER_CTX_set_padding(&kekctx, 0);
    382 	if(EVP_CIPHER_asn1_to_param(&kekctx, kekalg->parameter) < 0)
    383 		{
    384 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
    385 				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
    386 		goto err;
    387 		}
    388 
    389 	algtmp = pwri->keyDerivationAlgorithm;
    390 
    391 	/* Finish password based key derivation to setup key in "ctx" */
    392 
    393 	if (EVP_PBE_CipherInit(algtmp->algorithm,
    394 				(char *)pwri->pass, pwri->passlen,
    395 				algtmp->parameter, &kekctx, en_de) < 0)
    396 		{
    397 		CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_EVP_LIB);
    398 		goto err;
    399 		}
    400 
    401 	/* Finally wrap/unwrap the key */
    402 
    403 	if (en_de)
    404 		{
    405 
    406 		if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, &kekctx))
    407 			goto err;
    408 
    409 		key = OPENSSL_malloc(keylen);
    410 
    411 		if (!key)
    412 			goto err;
    413 
    414 		if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, &kekctx))
    415 			goto err;
    416 		pwri->encryptedKey->data = key;
    417 		pwri->encryptedKey->length = keylen;
    418 		}
    419 	else
    420 		{
    421 		key = OPENSSL_malloc(pwri->encryptedKey->length);
    422 
    423 		if (!key)
    424 			{
    425 			CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
    426 							ERR_R_MALLOC_FAILURE);
    427 			goto err;
    428 			}
    429 		if (!kek_unwrap_key(key, &keylen,
    430 					pwri->encryptedKey->data,
    431 					pwri->encryptedKey->length, &kekctx))
    432 			{
    433 			CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT,
    434 							CMS_R_UNWRAP_FAILURE);
    435 			goto err;
    436 			}
    437 
    438 		ec->key = key;
    439 		ec->keylen = keylen;
    440 
    441 		}
    442 
    443 	r = 1;
    444 
    445 	err:
    446 
    447 	EVP_CIPHER_CTX_cleanup(&kekctx);
    448 
    449 	if (!r && key)
    450 		OPENSSL_free(key);
    451 	X509_ALGOR_free(kekalg);
    452 
    453 	return r;
    454 
    455 	}
    456