Coverage Report

Created: 2023-06-08 06:41

/src/openssl111/crypto/cms/cms_enc.c
Line
Count
Source (jump to first uncovered line)
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
0
{
25
0
    BIO *b;
26
0
    EVP_CIPHER_CTX *ctx;
27
0
    const EVP_CIPHER *ciph;
28
0
    X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
29
0
    unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
30
0
    unsigned char *tkey = NULL;
31
0
    size_t tkeylen = 0;
32
33
0
    int ok = 0;
34
35
0
    int enc, keep_key = 0;
36
37
0
    enc = ec->cipher ? 1 : 0;
38
39
0
    b = BIO_new(BIO_f_cipher());
40
0
    if (b == NULL) {
41
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
42
0
        return NULL;
43
0
    }
44
45
0
    BIO_get_cipher_ctx(b, &ctx);
46
47
0
    if (enc) {
48
0
        ciph = ec->cipher;
49
        /*
50
         * If not keeping key set cipher to NULL so subsequent calls decrypt.
51
         */
52
0
        if (ec->key)
53
0
            ec->cipher = NULL;
54
0
    } else {
55
0
        ciph = EVP_get_cipherbyobj(calg->algorithm);
56
57
0
        if (!ciph) {
58
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
59
0
            goto err;
60
0
        }
61
0
    }
62
63
0
    if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
64
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
65
0
               CMS_R_CIPHER_INITIALISATION_ERROR);
66
0
        goto err;
67
0
    }
68
69
0
    if (enc) {
70
0
        int ivlen;
71
72
0
        calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
73
0
        if (calg->algorithm == NULL) {
74
0
            CMSerr(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM);
75
0
            goto err;
76
0
        }
77
        /* Generate a random IV if we need one */
78
0
        ivlen = EVP_CIPHER_CTX_iv_length(ctx);
79
0
        if (ivlen > 0) {
80
0
            if (RAND_bytes(iv, ivlen) <= 0)
81
0
                goto err;
82
0
            piv = iv;
83
0
        }
84
0
    } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) {
85
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
86
0
               CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
87
0
        goto err;
88
0
    }
89
0
    tkeylen = EVP_CIPHER_CTX_key_length(ctx);
90
    /* Generate random session key */
91
0
    if (!enc || !ec->key) {
92
0
        tkey = OPENSSL_malloc(tkeylen);
93
0
        if (tkey == NULL) {
94
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
95
0
            goto err;
96
0
        }
97
0
        if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
98
0
            goto err;
99
0
    }
100
101
0
    if (!ec->key) {
102
0
        ec->key = tkey;
103
0
        ec->keylen = tkeylen;
104
0
        tkey = NULL;
105
0
        if (enc)
106
0
            keep_key = 1;
107
0
        else
108
0
            ERR_clear_error();
109
110
0
    }
111
112
0
    if (ec->keylen != tkeylen) {
113
        /* If necessary set key length */
114
0
        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
0
            if (enc || ec->debug) {
120
0
                CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
121
0
                       CMS_R_INVALID_KEY_LENGTH);
122
0
                goto err;
123
0
            } else {
124
                /* Use random key */
125
0
                OPENSSL_clear_free(ec->key, ec->keylen);
126
0
                ec->key = tkey;
127
0
                ec->keylen = tkeylen;
128
0
                tkey = NULL;
129
0
                ERR_clear_error();
130
0
            }
131
0
        }
132
0
    }
133
134
0
    if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
135
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
136
0
               CMS_R_CIPHER_INITIALISATION_ERROR);
137
0
        goto err;
138
0
    }
139
0
    if (enc) {
140
0
        calg->parameter = ASN1_TYPE_new();
141
0
        if (calg->parameter == NULL) {
142
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
143
0
            goto err;
144
0
        }
145
0
        if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) {
146
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
147
0
                   CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
148
0
            goto err;
149
0
        }
150
        /* If parameter type not set omit parameter */
151
0
        if (calg->parameter->type == V_ASN1_UNDEF) {
152
0
            ASN1_TYPE_free(calg->parameter);
153
0
            calg->parameter = NULL;
154
0
        }
155
0
    }
156
0
    ok = 1;
157
158
0
 err:
159
0
    if (!keep_key || !ok) {
160
0
        OPENSSL_clear_free(ec->key, ec->keylen);
161
0
        ec->key = NULL;
162
0
    }
163
0
    OPENSSL_clear_free(tkey, tkeylen);
164
0
    if (ok)
165
0
        return b;
166
0
    BIO_free(b);
167
0
    return NULL;
168
0
}
169
170
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
171
                              const EVP_CIPHER *cipher,
172
                              const unsigned char *key, size_t keylen)
173
0
{
174
0
    ec->cipher = cipher;
175
0
    if (key) {
176
0
        if ((ec->key = OPENSSL_malloc(keylen)) == NULL) {
177
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT, ERR_R_MALLOC_FAILURE);
178
0
            return 0;
179
0
        }
180
0
        memcpy(ec->key, key, keylen);
181
0
    }
182
0
    ec->keylen = keylen;
183
0
    if (cipher)
184
0
        ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
185
0
    return 1;
186
0
}
187
188
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
189
                               const unsigned char *key, size_t keylen)
190
0
{
191
0
    CMS_EncryptedContentInfo *ec;
192
0
    if (!key || !keylen) {
193
0
        CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
194
0
        return 0;
195
0
    }
196
0
    if (ciph) {
197
0
        cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
198
0
        if (!cms->d.encryptedData) {
199
0
            CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE);
200
0
            return 0;
201
0
        }
202
0
        cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
203
0
        cms->d.encryptedData->version = 0;
204
0
    } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) {
205
0
        CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA);
206
0
        return 0;
207
0
    }
208
0
    ec = cms->d.encryptedData->encryptedContentInfo;
209
0
    return cms_EncryptedContent_init(ec, ciph, key, keylen);
210
0
}
211
212
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
213
0
{
214
0
    CMS_EncryptedData *enc = cms->d.encryptedData;
215
0
    if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
216
0
        enc->version = 2;
217
0
    return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
218
0
}