1 /* 2 * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "internal/cryptlib.h" 11 #include <openssl/asn1t.h> 12 #include <openssl/pem.h> 13 #include <openssl/x509v3.h> 14 #include <openssl/err.h> 15 #include <openssl/cms.h> 16 #include <openssl/rand.h> 17 #include "cms_local.h" 18 19 /* CMS EncryptedData Utilities */ 20 21 /* Return BIO based on EncryptedContentInfo and key */ 22 23 BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) 24 { 25 BIO *b; 26 EVP_CIPHER_CTX *ctx; 27 const EVP_CIPHER *ciph; 28 X509_ALGOR *calg = ec->contentEncryptionAlgorithm; 29 unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; 30 unsigned char *tkey = NULL; 31 size_t tkeylen = 0; 32 33 int ok = 0; 34 35 int enc, keep_key = 0; 36 37 enc = ec->cipher ? 1 : 0; 38 39 b = BIO_new(BIO_f_cipher()); 40 if (b == NULL) { 41 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); 42 return NULL; 43 } 44 45 BIO_get_cipher_ctx(b, &ctx); 46 47 if (enc) { 48 ciph = ec->cipher; 49 /* 50 * If not keeping key set cipher to NULL so subsequent calls decrypt. 51 */ 52 if (ec->key) 53 ec->cipher = NULL; 54 } else { 55 ciph = EVP_get_cipherbyobj(calg->algorithm); 56 57 if (!ciph) { 58 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER); 59 goto err; 60 } 61 } 62 63 if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) { 64 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, 65 CMS_R_CIPHER_INITIALISATION_ERROR); 66 goto err; 67 } 68 69 if (enc) { 70 int ivlen; 71 72 calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx)); 73 if (calg->algorithm == NULL) { 74 CMSerr(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM); 75 goto err; 76 } 77 /* Generate a random IV if we need one */ 78 ivlen = EVP_CIPHER_CTX_iv_length(ctx); 79 if (ivlen > 0) { 80 if (RAND_bytes(iv, ivlen) <= 0) 81 goto err; 82 piv = iv; 83 } 84 } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) { 85 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, 86 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 87 goto err; 88 } 89 tkeylen = EVP_CIPHER_CTX_key_length(ctx); 90 /* Generate random session key */ 91 if (!enc || !ec->key) { 92 tkey = OPENSSL_malloc(tkeylen); 93 if (tkey == NULL) { 94 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); 95 goto err; 96 } 97 if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) 98 goto err; 99 } 100 101 if (!ec->key) { 102 ec->key = tkey; 103 ec->keylen = tkeylen; 104 tkey = NULL; 105 if (enc) 106 keep_key = 1; 107 else 108 ERR_clear_error(); 109 110 } 111 112 if (ec->keylen != tkeylen) { 113 /* If necessary set key length */ 114 if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { 115 /* 116 * Only reveal failure if debugging so we don't leak information 117 * which may be useful in MMA. 118 */ 119 if (enc || ec->debug) { 120 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, 121 CMS_R_INVALID_KEY_LENGTH); 122 goto err; 123 } else { 124 /* Use random key */ 125 OPENSSL_clear_free(ec->key, ec->keylen); 126 ec->key = tkey; 127 ec->keylen = tkeylen; 128 tkey = NULL; 129 ERR_clear_error(); 130 } 131 } 132 } 133 134 if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) { 135 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, 136 CMS_R_CIPHER_INITIALISATION_ERROR); 137 goto err; 138 } 139 if (enc) { 140 calg->parameter = ASN1_TYPE_new(); 141 if (calg->parameter == NULL) { 142 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); 143 goto err; 144 } 145 if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) { 146 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, 147 CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); 148 goto err; 149 } 150 /* If parameter type not set omit parameter */ 151 if (calg->parameter->type == V_ASN1_UNDEF) { 152 ASN1_TYPE_free(calg->parameter); 153 calg->parameter = NULL; 154 } 155 } 156 ok = 1; 157 158 err: 159 if (!keep_key || !ok) { 160 OPENSSL_clear_free(ec->key, ec->keylen); 161 ec->key = NULL; 162 } 163 OPENSSL_clear_free(tkey, tkeylen); 164 if (ok) 165 return b; 166 BIO_free(b); 167 return NULL; 168 } 169 170 int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 171 const EVP_CIPHER *cipher, 172 const unsigned char *key, size_t keylen) 173 { 174 ec->cipher = cipher; 175 if (key) { 176 if ((ec->key = OPENSSL_malloc(keylen)) == NULL) { 177 CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT, ERR_R_MALLOC_FAILURE); 178 return 0; 179 } 180 memcpy(ec->key, key, keylen); 181 } 182 ec->keylen = keylen; 183 if (cipher) 184 ec->contentType = OBJ_nid2obj(NID_pkcs7_data); 185 return 1; 186 } 187 188 int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, 189 const unsigned char *key, size_t keylen) 190 { 191 CMS_EncryptedContentInfo *ec; 192 if (!key || !keylen) { 193 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY); 194 return 0; 195 } 196 if (ciph) { 197 cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData); 198 if (!cms->d.encryptedData) { 199 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE); 200 return 0; 201 } 202 cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted); 203 cms->d.encryptedData->version = 0; 204 } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) { 205 CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA); 206 return 0; 207 } 208 ec = cms->d.encryptedData->encryptedContentInfo; 209 return cms_EncryptedContent_init(ec, ciph, key, keylen); 210 } 211 212 BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms) 213 { 214 CMS_EncryptedData *enc = cms->d.encryptedData; 215 if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs) 216 enc->version = 2; 217 return cms_EncryptedContent_init_bio(enc->encryptedContentInfo); 218 } 219