1 /* crypto/cms/cms_pwri.c */
   2 /* Written by Dr Stephen N Henson (steve@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@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         }