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